springboot集成钉钉,发送钉钉日报

目录

1.说明

2.示例

3.总结


1.说明

学习地图 - 钉钉开放平台

在钉钉开放文档中可以查看有关日志相关的api,主要用到以下几个api:

        ①获取模板详情

        ②获取用户发送日志的概要信息

        ③获取日志接收人员列表

        ④创建日志

发送日志时需要根据模板规定日志的格式,所以先获取要发送日志的模板信息,然后获取用户在最近一段时间内发送的日志的概要信息,并根据最新一次的日志信息获取日志的接收人员信息,然后调用创建日志的api,设置日志内容,及接收人员。

2.示例

依赖

        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
            <version>2.0.0</version>
        </dependency>

钉钉工具类

package com.kingagroot.info.common.tools.common;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.kingagroot.info.common.contants.CommonContants;
import com.kingagroot.info.common.tools.thirdparty.DingDingTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * @Author linaibo
 * @Date 2024/1/6 16:18
 * @Version 1.0
 */
@Component
public class DingTool {

    private static LogTool logTool;

    @Autowired
    public void setLogTool(LogTool logTool) {
        DingTool.logTool = logTool;
    }

    // 权限用户名
    private static String accessKey;
    // 权限密码
    private static String secret;
    // agent_id
    private static Long agentId;
    // tokenUrl
    private static String tokenUrl;
    // 发送消息url
    private static String sendMsgUrl;
    // 系统url
    private static String sysUrl;
    // 模板名称
    private static String dingTemplateName;
    // 模板url
    private static String dingTemplateUrl;
    // 创建日报url
    private static String dingCreateUrl;
    // 日志信息url
    private static String simpleListUrl;
    // 接收人信息url
    private static String receiverUrl;


    @NacosValue(value = "${dingding.appkey}", autoRefreshed = true)
    public void setAccessKey(String accessKey) {
        DingTool.accessKey = accessKey;
    }

    @NacosValue(value = "${dingding.appsecret}", autoRefreshed = true)
    public void setSecret(String secret) {
        DingTool.secret = secret;
    }

    @NacosValue(value = "${dingding.agentId}", autoRefreshed = true)
    public void setAgentId(Long agentId) {
        DingTool.agentId = agentId;
    }

    @NacosValue(value = "${dingding.gettoken}", autoRefreshed = true)
    public void setTokenUrl(String tokenUrl) {
        DingTool.tokenUrl = tokenUrl;
    }

    @NacosValue(value = "${dingding.sendMsg}", autoRefreshed = true)
    public void setSendMsgUrl(String sendMsgUrl) {
        DingTool.sendMsgUrl = sendMsgUrl;
    }

    @NacosValue(value = "${sys.url}", autoRefreshed = true)
    public void setSysUrl(String sysUrl) {
        DingTool.sysUrl = sysUrl;
    }

    @NacosValue(value = "${dingding.templateName}", autoRefreshed = true)
    public void setDingTemplateName(String dingTemplateName) {
        DingTool.dingTemplateName = dingTemplateName;
    }

    @NacosValue(value = "${dingding.templateUrl}", autoRefreshed = true)
    public void setDingTemplateUrl(String dingTemplateUrl) {
        DingTool.dingTemplateUrl = dingTemplateUrl;
    }

    @NacosValue(value = "${dingding.createUrl}", autoRefreshed = true)
    public void setDingCreateUrl(String dingCreateUrl) {
        DingTool.dingCreateUrl = dingCreateUrl;
    }

    @NacosValue(value = "${dingding.simpleListUrl}", autoRefreshed = true)
    public void setSimpleListUrl(String simpleListUrl) {
        DingTool.simpleListUrl = simpleListUrl;
    }

    @NacosValue(value = "${dingding.receiverUrl}", autoRefreshed = true)
    public void setReceiverUrl(String receiverUrl) {
        DingTool.receiverUrl = receiverUrl;
    }

    /**
     * 获取钉钉token
     *
     * @return
     */
    public static String getDingToken() {
        DingTalkClient client = new DefaultDingTalkClient(tokenUrl);
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(accessKey);
        request.setAppsecret(secret);
        request.setHttpMethod("GET");
        try {
            OapiGettokenResponse response = client.execute(request);
            if (response.isSuccess()) {
                // 调用成功返回token信息
                return response.getAccessToken();
            }
            // 调用接口异常,输出异常信息,发送钉钉通知
            processErrMsg("getDingToken", "获取钉钉token失败", JSON.toJSONString(response));
        } catch (Exception e) {
            // 调用接口异常,输出异常信息
            processErrMsg("getDingToken", "获取钉钉token失败", JSON.toJSONString(e));
        }
        return null;
    }

    public static void processErrMsg(String method, String errorMsg, String responseMsg, String... dingId) {
        StringBuilder errMsg = new StringBuilder();
        errMsg.append(errorMsg).append(",响应信息:").append(JSON.toJSONString(responseMsg));
        if (dingId.length != CommonContants.NUM_0) {
            errMsg.append(",钉钉id:").append(dingId[0]);
        }
        logTool.saveExceptionLog("", "DingTool", method, errMsg.toString());
        DingDingTool.sendDingMsg(errMsg.toString());
    }

    /**
     * 发送钉钉通知
     *
     * @param token
     * @param pwd
     * @param userCode
     */
    public static boolean sendMsg(String token, String pwd, String userCode) {
        DingTalkClient client = new DefaultDingTalkClient(sendMsgUrl);
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setAgentId(agentId);
        request.setUseridList(userCode);
        request.setToAllUser(false);

        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype("text");
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        StringBuilder content = new StringBuilder();
        content.append("系统地址: ");
        content.append(sysUrl);
        content.append("  ");
        content.append("密码: ");
        content.append(pwd);
        msg.getText().setContent(content.toString());
        request.setMsg(msg);

        try {
            OapiMessageCorpconversationAsyncsendV2Response result = client.execute(request, token);
            if (result.isSuccess()) {
                return true;
            }
            // 调用接口异常,输出异常信息
            processErrMsg("sendMsg", "发送钉钉消息(密码)失败", JSON.toJSONString(result));
        } catch (Exception e) {
            // 调用接口异常,输出异常信息
            processErrMsg("sendMsg", "发送钉钉消息(密码)失败", JSON.toJSONString(e));
        }
        return false;
    }

    /**
     * 发送钉钉通知
     *
     * @param token
     * @param message
     * @param dingId
     */
    public static void sendMessage(String token, String message, String dingId) {
        DingTalkClient client = new DefaultDingTalkClient(sendMsgUrl);
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setAgentId(agentId);
        // 设置接收者列表
        request.setUseridList(dingId);
        // 是否发送给公司全员
        request.setToAllUser(false);
        // 设置发送的消息类型及消息内容
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(CommonContants.TEXT);
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        msg.getText().setContent(message);
        request.setMsg(msg);
        try {
            OapiMessageCorpconversationAsyncsendV2Response result = client.execute(request, token);
            if (result.isSuccess()) {
                return;
            }
            // 调用接口异常,输出异常信息
            processErrMsg("sendMessage", "发送钉钉消息失败", JSON.toJSONString(result));
        } catch (Exception e) {
            // 调用接口异常,输出异常信息
            processErrMsg("sendMessage", "发送钉钉消息失败", JSON.toJSONString(e));
        }
    }


    /**
     * 查询钉钉模板信息
     *
     * @param token
     * @param dingId
     */
    public static OapiReportTemplateGetbynameResponse.ReportTemplateResponseVo getTemplate(String token, String dingId) {
        DingTalkClient client = new DefaultDingTalkClient(dingTemplateUrl);
        OapiReportTemplateGetbynameRequest req = new OapiReportTemplateGetbynameRequest();
        req.setUserid(dingId);
        req.setTemplateName(dingTemplateName);
        try {
            OapiReportTemplateGetbynameResponse rsp = client.execute(req, token);
            if (rsp.isSuccess()) {
                // 日志内容的校验
                if (CollUtil.isEmpty(rsp.getResult().getFields()) ||
                        !Objects.equals(rsp.getResult().getFields().get(0).getType(), CommonContants.LONG_1)) {
                    processErrMsg("getTemplate", "模板内容已经修改", JSON.toJSONString(rsp.getResult()), dingId);
                    sendMessage(token, "模板内容已经修改,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
                    return null;
                }
                return rsp.getResult();
            }
            // 调用接口异常,输出异常信息,发送钉钉通知
            processErrMsg("getTemplate", "获取作物育种信息模板失败", JSON.toJSONString(rsp), dingId);
            sendMessage(token, "获取作物育种信息模板失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
        } catch (Exception e) {
            // 调用接口异常,输出异常信息,发送钉钉通知
            processErrMsg("getTemplate", "获取作物育种信息模板失败", JSON.toJSONString(e), dingId);
            sendMessage(token, "获取作物育种信息模板失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
        }
        return null;
    }


    /**
     * 获取用户在某个时间段的日志信息
     *
     * @param dingId
     * @param token
     * @return
     */
    public static OapiReportSimplelistResponse.ReportOapiVo getSimpleReport(String token, String dingId) {
        DingTalkClient client = new DefaultDingTalkClient(simpleListUrl);
        OapiReportSimplelistRequest req = new OapiReportSimplelistRequest();
        long endTime = System.currentTimeMillis();
        long startTime = Instant.now().minus(CommonContants.LONG_21, ChronoUnit.DAYS).toEpochMilli();
        req.setStartTime(startTime);
        req.setEndTime(endTime);
        req.setTemplateName(dingTemplateName);
        req.setUserid(dingId);
        req.setCursor(CommonContants.LONG_0);
        req.setSize(CommonContants.LONG_20);
        try {
            OapiReportSimplelistResponse rsp = client.execute(req, token);
            if (rsp.isSuccess()) {
                List<OapiReportSimplelistResponse.ReportOapiVo> dataList = rsp.getResult().getDataList();
                if (CollUtil.isEmpty(dataList)) {
                    DingDingTool.sendDingMsg("获取最近的日志信息为空,钉钉id:" + dingId);
                    sendMessage(token, "获取最近的日志信息为空,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
                    return null;
                } else {
                    // 获取最新一次的日报信息
                    Optional<OapiReportSimplelistResponse.ReportOapiVo> lastReport = dataList.stream()
                            .max(Comparator.comparingLong(OapiReportSimplelistResponse.ReportOapiVo::getCreateTime));
                    return lastReport.get();
                }
            }
            processErrMsg("getSimpleReport", "获取最近的日志信息失败", JSON.toJSONString(rsp), dingId);
            sendMessage(token, "获取最近的日志信息失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
        } catch (Exception e) {
            processErrMsg("getSimpleReport", "获取最近的日志信息失败", JSON.toJSONString(e), dingId);
            sendMessage(token, "获取最近的日志信息失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), dingId);
        }
        return null;
    }

    public static List<String> getReceiver(OapiReportSimplelistResponse.ReportOapiVo report, String token) {
        DingTalkClient client = new DefaultDingTalkClient(receiverUrl);
        OapiReportReceiverListRequest req = new OapiReportReceiverListRequest();
        req.setReportId(report.getReportId());
        try {
            OapiReportReceiverListResponse rsp = client.execute(req, token);
            if (rsp.isSuccess()) {
                List<String> useridList = rsp.getResult().getUseridList();
                if (CollUtil.isEmpty(useridList)) {
                    DingDingTool.sendDingMsg("查询的日志接收人信息为空,请求信息:" + JSON.toJSONString(report));
                    sendMessage(token, "查询的日志接收人信息为空,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), report.getCreatorId());
                    return null;
                }
                return useridList;
            }
            processErrMsg("getReceiver", "查询日志的接收人信息失败", JSON.toJSONString(rsp), report.getCreatorId());
            sendMessage(token, "查询日志的接收人信息失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), report.getCreatorId());
        } catch (Exception e) {
            processErrMsg("getReceiver", "查询日志的接收人信息失败", JSON.toJSONString(e), report.getCreatorId());
            sendMessage(token, "查询日志的接收人信息失败,系统无法进行日志推送,请自行发送。" + DateUtil.formatDateTime(new Date()), report.getCreatorId());
        }
        return null;
    }

    /**
     * 发送钉钉日报
     *
     * @param createDataParam
     * @param token
     */
    public static void createReport(OapiReportCreateRequest.OapiCreateReportParam createDataParam, String token) {
        DingTalkClient client = new DefaultDingTalkClient(dingCreateUrl);
        OapiReportCreateRequest req = new OapiReportCreateRequest();
        req.setCreateReportParam(createDataParam);
        try {
            OapiReportCreateResponse rsp = client.execute(req, token);
            if (!rsp.isSuccess()) {
                // 调用接口异常,输出异常信息
                processErrMsg("createReport", "发送日报失败", JSON.toJSONString(rsp), JSON.toJSONString(createDataParam));
                sendMessage(token, "系统发送日志失败,请自行发送。" + DateUtil.formatDateTime(new Date()), createDataParam.getUserid());
            }
        } catch (Exception e) {
            // 调用接口异常,输出异常信息
            processErrMsg("createReport", "发送日报失败", JSON.toJSONString(e), JSON.toJSONString(createDataParam));
            sendMessage(token, "系统发送日志失败,请自行发送。" + DateUtil.formatDateTime(new Date()), createDataParam.getUserid());
        }
    }
}

发送钉钉日报

    /**
     * 发送钉钉日报
     *
     * @param farmWorkMap
     */
    private void processDingTalkReports(Map<String, List<FarmInfoDto>> farmWorkMap) {
        // 钉钉id为空的用户列表,此类用户没有加入钉钉组织
        StringBuilder errUserId = new StringBuilder();
        // 循环农事信息列表,进行如下处理
        for (Map.Entry<String, List<FarmInfoDto>> farm : farmWorkMap.entrySet()) {
            // 用户及钉钉id
            String userId = farm.getKey();
            String dingId = farm.getValue().get(0).getDingId();
            // 钉钉id为空时,无法进行发送处理
            if (StrUtil.isBlank(dingId)) {
                errUserId.append(userId).append(",");
                continue;
            }
            // 获取钉钉的token信息
            String dingToken = getDingToken();
            if (StrUtil.isBlank(dingToken)) {
                continue;
            }
            // 获取模板信息
            OapiReportTemplateGetbynameResponse.ReportTemplateResponseVo template =
                    DingTool.getTemplate(dingToken, dingId);
            if (ObjectUtil.isNull(template)) {
                continue;
            }
            // 获取接收人信息
            OapiReportSimplelistResponse.ReportOapiVo simpleReport = DingTool.getSimpleReport(dingToken, dingId);
            List<String> receiver = new ArrayList<>();
            if (ObjectUtil.isNotNull(simpleReport)) {
                receiver = DingTool.getReceiver(simpleReport, dingToken);
            }
            if (CollUtil.isNotEmpty(receiver)) {
                // 构建发送日报的请求信息
                OapiReportCreateRequest.OapiCreateReportParam createDataParam = getCreateDataParam(template, farm, receiver);
                // 发送钉钉日报
                DingTool.createReport(createDataParam, dingToken);
            }
        }
        // 如果有问题的用户列表不为空,则将有问题的用户列表推送至钉钉群中
        if (StrUtil.isNotEmpty(errUserId)) {
            DingDingTool.sendDingMsg("以下用户不存在钉钉id,用户:" + errUserId);
        }
    }
    // 获取钉钉token
    public String getDingToken() {
        String dingDingToken = RedisTool.getString(redisEntr.getJedis(), CommonContants.DINGDING_TOKEN);
        if (StrUtil.isEmpty(dingDingToken)) {
            // 获取token
            dingDingToken = DingTool.getDingToken();
            // 存储token
            RedisTool.setString(redisEntr.getJedis(), CommonContants.DINGDING_TOKEN, dingDingToken, 5400);
        }
        return dingDingToken;
    }
 /**
     * 获取创建日报的请求信息
     *
     * @param template
     * @param farmMap
     */
    public OapiReportCreateRequest.OapiCreateReportParam getCreateDataParam(OapiReportTemplateGetbynameResponse.ReportTemplateResponseVo template,
                                                                            Map.Entry<String, List<FarmInfoDto>> farmMap,
                                                                            List<String> receivers) {
        // 获取模板内容信息
        List<OapiReportTemplateGetbynameResponse.Fields> fields = template.getFields();
        // 构建创建日报请求结构
        OapiReportCreateRequest.OapiCreateReportParam createReportParam = new OapiReportCreateRequest.OapiCreateReportParam();
        List<OapiReportCreateRequest.OapiReportContentVo> list = new ArrayList<>();
        OapiReportCreateRequest.OapiReportContentVo obj = new OapiReportCreateRequest.OapiReportContentVo();
        list.add(obj);
        // 添加日报内容,只添加模板的第一项
        OapiReportTemplateGetbynameResponse.Fields field = fields.get(0);
        obj.setSort(field.getSort());
        obj.setType(field.getType());
        obj.setContentType(CommonContants.MARKDOWN);
        StringBuilder farmInfo = new StringBuilder();
        for (int i = 0; i < farmMap.getValue().size(); i++) {
            FarmInfoDto farm = farmMap.getValue().get(i);
            farmInfo.append(i + 1).append(". ").append(farm.getBsName()).append(" ").append(farm.getFarmName()).append(" ");
            if (farm.getWorkCount().compareTo(BigDecimal.ZERO) > CommonContants.NUM_0) {
                farmInfo.append(farm.getWorkCount().stripTrailingZeros().toPlainString()).append(farm.getWorkValue()).append(" ");
            }
            if (StrUtil.isNotBlank(farm.getParticipants())) {
                farmInfo.append("参与人:").append(farm.getParticipants());
            }
            farmInfo.append("\n");
        }
        obj.setContent(farmInfo.toString());
        obj.setKey(field.getFieldName());
        createReportParam.setContents(list);
        // 设置汇报人信息
        createReportParam.setToUserids(receivers);
        // 设置模板id
        createReportParam.setTemplateId(template.getId());
        // 是否发送单聊消息
        createReportParam.setToChat(false);
        // 日志来源
        createReportParam.setDdFrom(CommonContants.TJNS);
        // 创建日志的用户id
        createReportParam.setUserid(template.getUserid());

        return createReportParam;
    }

3.总结

①我使用的是企业内部创建应用的方式,创建应用后可以拿到应用的凭证信息。

②要调用日志相关的接口,需要开通日志接口的权限信息,如下:

③测试时,可以创建一个企业账号,然后创建应用,并开通日志相关接口的权限,拉入相关人员,设置日志模板,并设置人员的上下级关系进行测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962303.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Node.js下载安装及环境配置教程 (详细版)

Node.js&#xff1a;是一个基于 Chrome V8 引擎的 JavaScript 运行时&#xff0c;用于构建可扩展的网络应用程序。Node.js 使用事件驱动、非阻塞 I/O 模型&#xff0c;使其非常适合构建实时应用程序。 Node.js 提供了一种轻量、高效、可扩展的方式来构建网络应用程序&#xff0…

ProfiNet转CANopen应用于汽车总装生产线输送设备ProfiNet与草棚CANopen质量检测系统

ProfiNet转CANopen协议转换网关模块&#xff0c;广泛应用于汽车行业。可替代NT 100-RE-CO和AB7658/7307产品功能 项目概述 在汽车总装生产线的末尾环节&#xff0c;汽车总装生产线输送设备起着关键的搬运作用&#xff0c;其基于 ProfiNet 协议运行&#xff0c;精准控制车辆在各…

「全网最细 + 实战源码案例」设计模式——桥接模式

核心思想 桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;将抽象部分与其实现部分分离&#xff0c;使它们可以独立变化。降低代码耦合度&#xff0c;避免类爆炸&#xff0c;提高代码的可扩展性。 结构 1. Implementation&#xff08;实现类…

Attention--人工智能领域的核心技术

1. Attention 的全称与基本概念 在人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;领域&#xff0c;Attention 机制的全称是 Attention Mechanism&#xff08;注意力机制&#xff09;。它是一种能够动态分配计算资源&#xff0c;使模型在处理输入数据…

DeepSeek能执行程序吗?

1. 前言 大过年的&#xff0c;继续蹭DeepSeek的热点&#xff0c;前面考察了DeepSeek能否进行推理&#xff08;DeekSeek能否进行逻辑推理&#xff09;&#xff0c;其实似乎没有结论&#xff0c;因为还没有到上难度&#xff0c;DeepSeek似乎就纠结在一些与推理无关的事情上了&am…

5.3.2 软件设计原则

文章目录 抽象模块化信息隐蔽与独立性衡量 软件设计原则&#xff1a;抽象、模块化、信息隐蔽。 抽象 抽象是抽出事物本质的共同特性。过程抽象是指将一个明确定义功能的操作当作单个实体看待。数据抽象是对数据的类型、操作、取值范围进行定义&#xff0c;然后通过这些操作对数…

STM32 TIM编码器接口测速

编码器接口简介&#xff1a; Encoder Interface 编码器接口 编码器接口可接收增量&#xff08;正交&#xff09;编码器的信号&#xff0c;根据编码器旋转产生的正交信号脉冲&#xff0c;自动控制CNT自增或自减&#xff0c;从而指示编码器的位置、旋转方向和旋转速度 每个高级定…

四.4 Redis 五大数据类型/结构的详细说明/详细使用( zset 有序集合数据类型详解和使用)

四.4 Redis 五大数据类型/结构的详细说明/详细使用&#xff08; zset 有序集合数据类型详解和使用&#xff09; 文章目录 四.4 Redis 五大数据类型/结构的详细说明/详细使用&#xff08; zset 有序集合数据类型详解和使用&#xff09;1. 有序集合 Zset(sorted set)2. zset 有序…

Spring AI 在微服务中的应用:支持分布式 AI 推理

1. 引言 在现代企业中&#xff0c;微服务架构 已成为开发复杂系统的主流方式&#xff0c;而 AI 模型推理 也越来越多地被集成到业务流程中。如何在分布式微服务架构下高效地集成 Spring AI&#xff0c;使多个服务可以协同完成 AI 任务&#xff0c;并支持分布式 AI 推理&#x…

使用Ollama和Open WebUI快速玩转大模型:简单快捷的尝试各种llm大模型,比如DeepSeek r1

Ollama本身就是非常优秀的大模型管理和推理组件&#xff0c;再使用Open WebUI更加如虎添翼&#xff01; Ollama快速使用指南 安装Ollama Windows下安装 下载Windows版Ollama软件&#xff1a;Release v0.5.7 ollama/ollama GitHub 下载ollama-windows-amd64.zip这个文件即可…

EasyExcel写入和读取多个sheet

最近在工作中&#xff0c;作者频频接触到Excel处理&#xff0c;因此也对EasyExcel进行了一定的研究和学习&#xff0c;也曾困扰过如何处理多个sheet&#xff0c;因此此处分享给大家&#xff0c;希望能有所帮助 目录 1.依赖 2. Excel类 3.处理Excel读取和写入多个sheet 4. 执…

《DeepSeek 网页/API 性能异常(DeepSeek Web/API Degraded Performance):网络安全日志》

DeepSeek 网页/API 性能异常&#xff08;DeepSeek Web/API Degraded Performance&#xff09;订阅 已识别 - 已识别问题&#xff0c;并且正在实施修复。 1月 29&#xff0c; 2025 - 20&#xff1a;57 CST 更新 - 我们将继续监控任何其他问题。 1月 28&#xff0c; 2025 - 22&am…

安卓(android)饭堂广播【Android移动开发基础案例教程(第2版)黑马程序员】

一、实验目的&#xff08;如果代码有错漏&#xff0c;可查看源码&#xff09; 1.熟悉广播机制的实现流程。 2.掌握广播接收者的创建方式。 3.掌握广播的类型以及自定义官博的创建。 二、实验条件 熟悉广播机制、广播接收者的概念、广播接收者的创建方式、自定广播实现方式以及有…

分享|借鉴传统操作系统中分层内存系统的理念(虚拟上下文管理技术)提升LLMs在长上下文中的表现

《MemGPT: Towards LLMs as Operating Systems》 结论&#xff1a; 大语言模型&#xff08;LLMs&#xff09;上下文窗口受限问题的背景下&#xff0c; 提出了 MemGPT&#xff0c;通过类操作系统的分层内存系统的虚拟上下文管理技术&#xff0c; 提升 LLMs 在复杂人物&#…

games101-作业3

由于此次试验需要加载模型&#xff0c;涉及到本地环节&#xff0c;如果是windows系统&#xff0c;需要对main函数中的路径稍作改变&#xff1a; 这么写需要&#xff1a; #include "windows.h" 该段代码&#xff1a; #include "windows.h" int main(int ar…

Spring Boot 日志:项目的“行车记录仪”

一、什么是Spring Boot日志 &#xff08;一&#xff09;日志引入 在正式介绍日志之前&#xff0c;我们先来看看上篇文章中&#xff08;Spring Boot 配置文件&#xff09;中的验证码功能的一个代码片段&#xff1a; 这是一段校验用户输入的验证码是否正确的后端代码&#xff0c…

【大厂AI实践】OPPO:大规模知识图谱及其在小布助手中的应用

导读&#xff1a;OPPO知识图谱是OPPO数智工程系统小布助手团队主导、多团队协作建设的自研大规模通用知识图谱&#xff0c;目前已达到数亿实体和数十亿三元组的规模&#xff0c;主要落地在小布助手知识问答、电商搜索等场景。 本文主要分享OPPO知识图谱建设过程中算法相关的技…

机器学习周报-文献阅读

文章目录 摘要Abstract 1 相关知识1.1 WDN建模1.2 掩码操作&#xff08;Masking Operation&#xff09; 2 论文内容2.1 WDN信息的数据处理2.2 使用所收集的数据构造模型2.2.1 Gated graph neural network2.2.2 Masking operation2.2.3 Training loss2.2.4 Evaluation metrics 2…

工具的应用——安装copilot

一、介绍Copilot copilot是一个AI辅助编程的助手&#xff0c;作为需要拥抱AI的程序员可以从此尝试进入&#xff0c;至于好与不好&#xff0c;应当是小马过河&#xff0c;各有各的心得。这里不做评述。重点在安装copilot的过程中遇到了一些问题&#xff0c;然后把它总结下&…

后盾人JS--闭包明明白白

延伸函数环境生命周期 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> <…