wangyunpeng 1 ヶ月 前
コミット
78ab262778

+ 50 - 43
core/src/main/java/com/tzld/supply/job/ContentScreenJob.java

@@ -180,53 +180,60 @@ public class ContentScreenJob {
     }
 
     private String precisionScreenPrompt = "你是一名内容智能分析与编辑顾问,负责对新闻或视频进行全面分析。请根据以下内容,判断其是否适合老年群体推荐,并输出结构化结果。\n" +
-            "\n" +
             "分析目标:\n" +
-            "1. 判断是否适合老年人阅读:\n" +
-            "   内容应具备健康、生活、历史、天气、节假日、社会正能量等特征;避免涉及复杂科技、互联网、游戏、金融投机等难以理解或风险性内容。\n" +
-            "   语言表达应平实易懂,不含网络黑话、缩写或复杂术语。\n" +
-            "2. 判断是否包含政治、敏感、广告或负面内容:\n" +
-            "   政治:涉及国家政策、领导人、外交等信息;\n" +
-            "   敏感:涉及宗教、种族、灾难、社会冲突等;\n" +
-            "   负面:传播焦虑、恐慌、暴力、疾病死亡等信息;\n" +
-            "   广告:带有明显推广目的,如品牌、价格、产品功能描述等。\n" +
-            "3. 判断内容主题、地域、关键词:\n" +
-            "   主题:健康、生活、历史、天气、节假日、军事、社会、其他;\n" +
-            "   地域:提取与城市、省份或国家相关的地域信息;\n" +
-            "   关键词:提取3~5个能代表内容核心的热词。\n" +
-            "4. 判断是否可以在不误导、不造假的前提下适度夸大或优化标题:\n" +
-            "   夸大标准包括:是否能使用更具吸引力的词汇(如“意想不到”、“太实用了”、“医生都建议”、“家家都能用上”等),但不能改变事实或造成误导。\n" +
-            "5. 提取内容亮点与传播潜力:\n" +
-            "   内容亮点:是否包含实用技巧、经验分享、生活智慧或积极故事;\n" +
-            "   传播潜力:判断是否具备高关注度话题、共鸣性或视觉吸引力(如图片、视频内容)。\n" +
-            "6. 给出传播评分和推荐评分:\n" +
-            "   传播评分(0.0~1.0):根据内容话题性、情绪感染力、关键词热度等评估;\n" +
-            "   推荐评分(0.0~1.0):根据内容积极性、老年适配度、价值导向评估。\n" +
-            "7. 若适合改写,请输出更吸引人的标题:\n" +
-            "   若标题平淡但内容有亮点,可提出优化建议或改写方案,使其更具吸引力和传播性。\n" +
+            "判断是否适合老年人阅读:\n" +
+            " 内容应具备健康、生活、历史、天气、节假日、社会正能量等特征;避免涉及复杂科技、互联网、游戏、金融投机等难以理解或风险性内容。\n" +
+            " 语言表达应平实易懂,不含网络黑话、缩写或复杂术语。\n" +
+            "判断是否包含政治、敏感、广告或负面内容:\n" +
+            " 政治:涉及国家政策、领导人、外交等信息;\n" +
+            " 敏感:涉及宗教、种族、灾难、社会冲突等;\n" +
+            " 负面:传播焦虑、恐慌、暴力、疾病死亡等信息;\n" +
+            " 广告:带有明显推广目的,如品牌、价格、产品功能描述等。\n" +
+            "判断内容主题、地域、关键词:\n" +
+            " 主题:健康、生活、历史、天气、节假日、军事、社会、其他;\n" +
+            " 地域:提取与城市、省份或国家相关的地域信息;\n" +
+            " 关键词:提取3~5个能代表内容核心的热词。\n" +
+            "判断是否可以在不误导、不造假的前提下适度夸大或优化标题:\n" +
+            " 夸大标准包括:是否能使用更具吸引力的词汇(如“意想不到”、“太实用了”、“医生都建议”、“家家都能用上”等),但不能改变事实或造成误导。\n" +
+            "提取内容亮点与传播潜力:\n" +
+            " 内容亮点:是否包含实用技巧、经验分享、生活智慧或积极故事;\n" +
+            " 传播潜力:判断是否具备高关注度话题、共鸣性或视觉吸引力(如图片、视频内容)。\n" +
+            "给出传播评分和推荐评分:\n" +
+            " 传播评分(0.0~1.0):根据内容话题性、情绪感染力、关键词热度等评估;\n" +
+            " 推荐评分(0.0~1.0):根据内容积极性、老年适配度、价值导向评估。\n" +
+            "若适合改写,请输出更吸引人的标题:\n" +
+            " 若标题平淡但内容有亮点,可提出优化建议或改写方案,使其更具吸引力和传播性。\n" +
+            "生成口播稿:\n" +
+            " 在300至500字之间,用口语化、温和、易理解的语言生成一段适合新闻类短视频播报的口播内容。\n" +
+            " 要求:\n" +
+            "用第三人称叙述方式讲述新闻核心信息;\n" +
+            "表达自然、生动,符合老年人理解习惯;\n" +
+            "语气积极、温暖,避免复杂句式;\n" +
+            "可加入轻微引导或总结语,如“这条消息提醒我们”、“大家平时也要注意”等。\n" +
             "\n" +
             "请严格按以下 JSON 格式输出,不要输出任何解释说明:\n" +
             "{\n" +
-            "  \"is_elderly_suitable\": true/false,\n" +
-            "  \"is_sensitive\": true/false,\n" +
-            "  \"is_negative\": true/false,\n" +
-            "  \"is_advertisement\": true/false,\n" +
-            "  \"value_category\": \"健康/生活/历史/天气/节假日/军事/社会/其他\",\n" +
-            "  \"region\": \"北京/上海/全国/未知\",\n" +
-            "  \"hot_keywords\": [\"keyword1\", \"keyword2\", \"keyword3\"],\n" +
-            "  \"summary\": \"一句话总结新闻核心内容\",\n" +
-            "  \"highlight_potential\": true/false,\n" +
-            "  \"highlight_reason\": \"如果能增强吸引力,说明如何优化内容表达\",\n" +
-            "  \"can_be_exaggerated\": true/false,\n" +
-            "  \"exaggeration_type\": \"标题可优化/内容可强化/无可夸大点\",\n" +
-            "  \"improved_title\": \"若可改写,请给出更吸引人的标题\",\n" +
-            "  \"propagation_score\": 0.0~1.0,\n" +
-            "  \"suitability_score\": 0.0~1.0,\n" +
-            "  \"reason\": \"综合说明判断依据\"\n" +
-            "}\n" +
+            " \"is_elderly_suitable\": true/false,\n" +
+            " \"is_sensitive\": true/false,\n" +
+            " \"is_negative\": true/false,\n" +
+            " \"is_advertisement\": true/false,\n" +
+            " \"value_category\": \"健康/生活/历史/天气/节假日/军事/社会/其他\",\n" +
+            " \"region\": \"北京/上海/全国/未知\",\n" +
+            " \"hot_keywords\": [\"keyword1\", \"keyword2\", \"keyword3\"],\n" +
+            " \"summary\": \"一句话总结新闻核心内容\",\n" +
+            " \"highlight_potential\": true/false,\n" +
+            " \"highlight_reason\": \"如果能增强吸引力,说明如何优化内容表达\",\n" +
+            " \"can_be_exaggerated\": true/false,\n" +
+            " \"exaggeration_type\": \"标题可优化/内容可强化/无可夸大点\",\n" +
+            " \"improved_title\": \"若可改写,请给出更吸引人的标题\",\n" +
+            " \"propagation_score\": 0.0~1.0,\n" +
+            " \"suitability_score\": 0.0~1.0,\n" +
+            " \"reason\": \"综合说明判断依据\",\n" +
+            " \"narration_script\": \"生成一段300到500字的口播内容,语言自然、贴近生活、表达温和\"\n" +
+            " }\n" +
             "\n" +
-            "【输入内容】\n" +
-            "标题:{{title}}\n" +
-            "正文:{{content}}";
+            "输入内容:\n" +
+            " 标题:{{title}}\n" +
+            " 正文:{{content}}";
 
 }

+ 4 - 0
core/src/main/java/com/tzld/supply/job/SpiderContentFeishuJob.java

@@ -9,6 +9,7 @@ import com.tzld.supply.model.entity.PrecisionScreenEntity;
 import com.tzld.supply.model.entity.feishu.SpiderContentEntity;
 import com.tzld.supply.model.po.supply.spider.SpiderContent;
 import com.tzld.supply.model.po.supply.spider.SpiderContentExample;
+import com.tzld.supply.util.DateUtils;
 import com.tzld.supply.util.feishu.FeiShu;
 import com.tzld.supply.util.feishu.FeishuExcelUtil;
 import com.xxl.job.core.biz.model.ReturnT;
@@ -44,12 +45,15 @@ public class SpiderContentFeishuJob {
         List<SpiderContentEntity> exportList = new ArrayList<>();
         for (SpiderContent spiderContent : dataList) {
             SpiderContentEntity spiderContentEntity = new SpiderContentEntity();
+            spiderContentEntity.setDate(DateUtils.getDateString(spiderContent.getCreateTime(), "yyyy-MM-dd"));
             spiderContentEntity.setSource(spiderContent.getSource() + "-" + spiderContent.getSourceType());
             spiderContentEntity.setTitle(spiderContent.getTitle());
             spiderContentEntity.setStatus(SpiderContentStatusEnum.getByCode(spiderContent.getStatus()).getMsg());
             if (StringUtils.isNotBlank(spiderContent.getAiPrecisionResult())) {
                 PrecisionScreenEntity entity = JSONObject.parseObject(spiderContent.getAiPrecisionResult(), PrecisionScreenEntity.class);
                 spiderContentEntity.setImprovedTitle(entity.getImprovedTitle());
+                spiderContentEntity.setFilterReason(entity.getReason());
+                spiderContentEntity.setNarrationScript(entity.getNarrationScript());
             }
             spiderContentEntity.setContent(spiderContent.getContent());
             exportList.add(spiderContentEntity);

+ 1 - 0
core/src/main/java/com/tzld/supply/model/entity/PrecisionScreenEntity.java

@@ -21,5 +21,6 @@ public class PrecisionScreenEntity {
     private Double propagationScore;
     private Double suitabilityScore;
     private String reason;
+    private String narrationScript;
 
 }

+ 3 - 0
core/src/main/java/com/tzld/supply/model/entity/feishu/SpiderContentEntity.java

@@ -4,9 +4,12 @@ import lombok.Data;
 
 @Data
 public class SpiderContentEntity {
+    private String date;
     private String source;
     private String title;
     private String status;
     private String improvedTitle;
+    private String filterReason;
     private String content;
+    private String narrationScript;
 }

+ 318 - 0
core/src/main/java/com/tzld/supply/util/DateUtils.java

@@ -0,0 +1,318 @@
+package com.tzld.supply.util;
+
+import org.springframework.util.StringUtils;
+
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+
+/**
+ * @author dyp
+ */
+public final class DateUtils {
+    public static String getCurrentDateStr(String format) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+        Date currentDate = new Date();
+        return dateFormat.format(currentDate);
+    }
+
+    public static int getCurrentHour() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+        return calendar.get(Calendar.HOUR_OF_DAY);
+    }
+
+    public static String getBeforeDaysDateStr(String format, int d) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+        calendar.setTime(new Date());
+        calendar.add(Calendar.DAY_OF_MONTH, -d);
+        Date previousDate = calendar.getTime();
+        return dateFormat.format(previousDate);
+    }
+
+    public static String getBeforeDaysDateStr(String dateStr, String format, int d) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+        Date date = new Date();
+        try {
+            date = dateFormat.parse(dateStr);
+        } catch (Exception ignore) {}
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+        calendar.setTime(date);
+        calendar.add(Calendar.DAY_OF_MONTH, -d);
+        Date previousDate = calendar.getTime();
+        return dateFormat.format(previousDate);
+    }
+
+
+    public static boolean ifTimeRangeInNow(String timeRange) {
+        try {
+
+            String[] split = timeRange.split("-");
+            if (split.length != 2) {
+                return false;
+            }
+            String startTime = split[0];
+            String endTime = split[1];
+            if (startTime.length() != 10 || endTime.length() != 10) {
+                return false;
+            }
+            LocalDateTime now = LocalDateTime.now();
+            LocalDateTime start = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyyMMddHH"));
+            LocalDateTime end = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyyMMddHH"));
+            return now.equals(start) || (now.isAfter(start) && now.isBefore(end));
+        } catch (Exception e) {
+//            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public static long dateStrToTimestamp(String dateStr, String format) {
+        // 定义日期格式
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
+
+        // 解析输入的日期字符串为LocalDate对象
+        LocalDate date = LocalDate.parse(dateStr, formatter);
+
+        // 将LocalDate转换为LocalDateTime,时间部分设为00:00:00
+        LocalDateTime dateTime = date.atStartOfDay();
+
+        // 定义北京时区
+        ZoneId zone = ZoneId.of("Asia/Shanghai");
+
+        // 将LocalDateTime转换为时间戳(秒数),使用北京时区
+        return dateTime.toEpochSecond(zone.getRules().getOffset(dateTime));
+    }
+
+    public static boolean isValidDate(String dateString) {
+        // 定义日期格式
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+        try {
+            // 尝试解析日期字符串
+            LocalDate date = LocalDate.parse(dateString, dateFormatter);
+            return true; // 如果解析成功,返回 true
+        } catch (DateTimeParseException e) {
+            return false; // 如果解析失败,返回 false
+        }
+    }
+
+    public static String timestampToYMDStr(Long timestamp, String format) {
+
+        // 定义北京时区
+        ZoneId zone = ZoneId.of("Asia/Shanghai");
+
+        // 将时间戳转换为LocalDateTime
+        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), zone);
+
+        // 定义日期格式为"yyyyMMddHHmmss"
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
+
+        // 将LocalDateTime格式化为字符串
+        return dateTime.format(formatter);
+    }
+
+    public static String findNearestDate(List<String> dateList, String targetDateStr, String format) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
+        // 将目标日期字符串转换为 LocalDate
+        LocalDate targetDate = LocalDate.parse(targetDateStr, formatter);
+
+        // 初始化最近的日期和最小的天数差值
+        String nearestDateStr = null;
+        long minDiff = Long.MAX_VALUE;
+
+        // 遍历日期列表,找到最近的日期
+        for (String dateStr : dateList) {
+            LocalDate currentDate = LocalDate.parse(dateStr, formatter);
+            long diff = Math.abs(ChronoUnit.DAYS.between(currentDate, targetDate));  // 计算天数差异
+
+            // 如果找到更小的差异,更新最近的日期
+            if (diff < minDiff) {
+                minDiff = diff;
+                nearestDateStr = dateStr;
+            }
+        }
+
+        return nearestDateStr;  // 返回最近的日期字符串
+    }
+
+    public static List<String> getBeforeDays(String beginDate, String endDate, int days) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
+        // 获取今天的日期
+        LocalDate today = LocalDate.now();
+        if (!StringUtils.hasText(beginDate)) {
+            beginDate = today.format(formatter);
+        }
+        if (!StringUtils.hasText(endDate)) {
+            endDate = today.format(formatter);
+        }
+        // 解析输入的日期字符串为LocalDate对象
+        LocalDate date = LocalDate.parse(beginDate, formatter);
+        LocalDate end = LocalDate.parse(endDate, formatter);
+        // 获取从输入日期前三天的日期
+        LocalDate startDate = date.minusDays(days);
+        // 存储所有日期的列表
+        List<String> datesList = new ArrayList<>();
+        // 从startDate到today遍历日期
+        while (startDate.isBefore(today) && !startDate.isAfter(end)) {
+            // 将当前日期格式化为"yyyyMMdd"并添加到列表中
+            datesList.add(startDate.format(formatter));
+            // 日期加1天
+            startDate = startDate.plusDays(1);
+        }
+        return datesList;
+    }
+
+    // 获取每日最小秒数 (当天零点)
+    public static Long getStartOfDay(String dateStr, String formatter) {
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat(formatter);
+            Date date = sdf.parse(dateStr);
+
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+            calendar.setTime(date);
+            calendar.set(Calendar.HOUR_OF_DAY, 0);
+            calendar.set(Calendar.MINUTE, 0);
+            calendar.set(Calendar.SECOND, 0);
+            calendar.set(Calendar.MILLISECOND, 0);
+
+            return calendar.getTimeInMillis() / 1000;
+        } catch (Exception e) {
+            Date date = new Date();
+            return date.getTime() / 1000;
+        }
+    }
+
+    public static Date getStartDateOfDay(Long timestamp) {
+        try {
+            Calendar calendar = Calendar.getInstance();
+            // 设置时区为UTC(你可以根据需要更改时区)
+            calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+            // 将时间戳转换为毫秒并设置时间
+            calendar.setTimeInMillis(timestamp * 1000L);
+            calendar.set(Calendar.HOUR_OF_DAY, 0);
+            calendar.set(Calendar.MINUTE, 0);
+            calendar.set(Calendar.SECOND, 0);
+            calendar.set(Calendar.MILLISECOND, 0);
+
+            return calendar.getTime();
+        } catch (Exception e) {
+            return new Date();
+        }
+    }
+
+    // 获取每日最大秒数 (当天的23:59:59)
+    public static Long getEndOfDay(String dateStr, String formatter) {
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat(formatter);
+            Date date = sdf.parse(dateStr);
+
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+            calendar.setTime(date);
+            calendar.set(Calendar.HOUR_OF_DAY, 23);
+            calendar.set(Calendar.MINUTE, 59);
+            calendar.set(Calendar.SECOND, 59);
+            calendar.set(Calendar.MILLISECOND, 999);
+
+            return calendar.getTimeInMillis() / 1000;
+        } catch (Exception e) {
+            Date date = new Date();
+            return date.getTime() / 1000;
+        }
+    }
+
+    public static Integer getHourByTimestamp(Long timestamp) {
+        Calendar calendar = Calendar.getInstance();
+        // 设置时区为UTC(你可以根据需要更改时区)
+        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+        // 将时间戳转换为毫秒并设置时间
+        calendar.setTimeInMillis(timestamp * 1000L);
+        // 获取小时
+        return calendar.get(Calendar.HOUR_OF_DAY);
+    }
+
+    public static int getMinuteByTimestamp(long timestamp) {
+        Calendar calendar = Calendar.getInstance();
+        // 设置时区为UTC(你可以根据需要更改时区)
+        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+        // 将时间戳转换为毫秒并设置时间
+        calendar.setTimeInMillis(timestamp * 1000L);
+        // 获取小时
+        return calendar.get(Calendar.MINUTE);
+    }
+
+
+    public static void main(String[] args) {
+        Calendar calendar = Calendar.getInstance();
+
+        System.out.println((calendar.get(Calendar.DAY_OF_WEEK) + 6) % 7);
+        System.out.println(new SimpleDateFormat("yyyyMMdd").format(calendar.getTime()));
+        System.out.println(new SimpleDateFormat("HH").format(calendar.getTime()));
+
+    }
+
+    public static Long getTodayStart() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTime().getTime();
+    }
+
+    public static Long getBeforeDayStart(int days) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        calendar.add(Calendar.DAY_OF_MONTH, -days);
+        return calendar.getTime().getTime() / 1000;
+    }
+
+    public static String getBeforeDayStr(String dateStr, String format, int days) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
+        LocalDate date = LocalDate.parse(dateStr, formatter);
+        date = date.minusDays(days);
+        return date.format(formatter);
+    }
+
+    public static String getDateString(Long timestamp) {
+        // 创建日期时间格式化器
+        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyyMMdd");
+        // 将时间戳转换为 LocalDateTime
+        ZoneId zone = ZoneId.of("Asia/Shanghai");
+        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), zone);
+        // 格式化日期时间并返回
+        return dateTime.format(dateFormat);
+    }
+
+    public static String getDateString(Long timestamp, String pattern) {
+        // 创建日期时间格式化器
+        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(pattern);
+        // 将时间戳转换为 LocalDateTime
+        ZoneId zone = ZoneId.of("Asia/Shanghai");
+        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), zone);
+        // 格式化日期时间并返回
+        return dateTime.format(dateFormat);
+    }
+
+    public static Date getDate(String dateString) {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        LocalDate localDate = LocalDate.parse(dateString, formatter);
+        ZoneId zone = ZoneId.of("Asia/Shanghai");
+        return Date.from(localDate.atStartOfDay(zone).toInstant());
+    }
+}