Compare commits

..

3 Commits

Author SHA1 Message Date
ArvinLovegood
5af0e28601 feat(telegraph):电报标签功能和前端显示优化
- 实现电报数据的标签关联功能,支持主题标签存储
- 添加电报列表分页查询接口,支持标签预加载
- 在前端新闻列表组件中添加时间显示功能
- 优化新闻列表按日期分组显示的布局结构
- 添加定时刷新财联社电报、新浪财经和外媒数据功能
- 根据新闻列表长度动态调整网格列数显示
2026-01-01 12:00:32 +08:00
ArvinLovegood
c4af77954e refactor(app):将syncNews函数改为方法并集成情感分析
- 将syncNews函数转换为App结构体的方法
- 在新闻同步逻辑中集成情感分析功能
- 添加新闻推送功能到同步流程中
- 修复VIP用户新闻同步的调用方式
2026-01-01 09:07:25 +08:00
ArvinLovegood
8236adb680 feat(news):添加新闻标签旋转灯标识处理
- 新增 rotating_light 标签检测逻辑
- 根据标签内容动态设置 isRed 属性
- 优化新闻电报数据结构的红色标识字段处理
2026-01-01 08:48:01 +08:00
4 changed files with 81 additions and 13 deletions

24
app.go
View File

@@ -261,7 +261,7 @@ func (a *App) CheckUpdate(flag int) {
if _, vipLevel, ok := a.isVip(sponsorCode, "", releaseVersion); ok {
level, _ := convertor.ToInt(vipLevel)
if level >= 2 {
go syncNews()
go a.syncNews()
}
}
@@ -409,7 +409,7 @@ func (a *App) isVip(sponsorCode string, downloadUrl string, releaseVersion *mode
return downloadUrl, vipLevel, isVip
}
func syncNews() {
func (a *App) syncNews() {
defer PanicHandler()
client := resty.New()
url := fmt.Sprintf("http://go-stock.sparkmemory.top:16666/FinancialNews/json?since=%d", time.Now().Add(-24*time.Hour).Unix())
@@ -432,14 +432,18 @@ func syncNews() {
dataTime := time.UnixMilli(int64(news.Time * 1000))
if slice.ContainAny(news.Tags, []string{"外媒资讯", "财联社电报", "新浪财经"}) {
isRed := false
if slice.Contain(news.Tags, "rotating_light") {
isRed = true
}
telegraph := &models.Telegraph{
Title: news.Title,
Content: news.Message,
DataTime: &dataTime,
IsRed: false,
IsRed: isRed,
Time: dataTime.Format("15:04:05"),
Source: GetSource(news.Tags),
SentimentResult: "",
SentimentResult: data.AnalyzeSentiment(news.Message).Description,
}
cnt := int64(0)
if telegraph.Title == "" {
@@ -449,6 +453,18 @@ func syncNews() {
}
if cnt == 0 {
db.Dao.Model(telegraph).Create(&telegraph)
a.NewsPush(&[]models.Telegraph{*telegraph})
for _, subject := range news.Tags {
tag := &models.Tags{
Name: subject,
Type: "subject",
}
db.Dao.Model(tag).Where("name=? and type=?", subject, "subject").FirstOrCreate(&tag)
db.Dao.Model(models.TelegraphTags{}).Where("telegraph_id=? and tag_id=?", telegraph.ID, tag.ID).FirstOrCreate(&models.TelegraphTags{
TelegraphId: telegraph.ID,
TagId: tag.ID,
})
}
}
}
}

View File

@@ -228,6 +228,29 @@ func (m MarketNewsApi) GetTelegraphList(source string) *[]*models.Telegraph {
}
return news
}
func (m MarketNewsApi) GetTelegraphListWithPaging(source string, page, pageSize int) *[]*models.Telegraph {
// 计算偏移量
offset := (page - 1) * pageSize
news := &[]*models.Telegraph{}
if source != "" {
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("data_time desc,time desc").Limit(pageSize).Offset(offset).Find(news)
} else {
db.Dao.Model(news).Preload("TelegraphTags").Order("data_time desc,time desc").Limit(pageSize).Offset(offset).Find(news)
}
for _, item := range *news {
tags := &[]models.Tags{}
db.Dao.Model(&models.Tags{}).Where("id in ?", lo.Map(item.TelegraphTags, func(item models.TelegraphTags, index int) uint {
return item.TagId
})).Find(&tags)
tagNames := lo.Map(*tags, func(item models.Tags, index int) string {
return item.Name
})
item.SubjectTags = tagNames
logger.SugaredLogger.Infof("tagNames %v SubjectTags%s", tagNames, item.SubjectTags)
}
return news
}
func (m MarketNewsApi) GetSinaNews(crawlTimeOut uint) *[]models.Telegraph {
news := &[]models.Telegraph{}

View File

@@ -128,6 +128,9 @@ onBeforeMount(() => {
indexIndustryRank.value = setInterval(() => {
industryRank()
ReFlesh("财联社电报")
ReFlesh("新浪财经")
ReFlesh("外媒")
}, 1000 * 10)
@@ -354,14 +357,14 @@ function ReFlesh(source) {
<AnalyzeMartket :dark-theme="darkTheme" :chart-height="300" :kDays="1" :name="'最近24小时热词'" />
</n-gi>
<n-gi>
<n-grid :cols="httpProxyEnabled?3:2" :y-gap="0">
<n-grid :cols="foreignNewsList.length?3:2" :y-gap="0">
<n-gi>
<news-list :newsList="telegraphList" :header-title="'财联社电报'" @update:message="ReFlesh"></news-list>
</n-gi>
<n-gi>
<news-list :newsList="sinaNewsList" :header-title="'新浪财经'" @update:message="ReFlesh"></news-list>
</n-gi>
<n-gi v-if="httpProxyEnabled">
<n-gi v-if="foreignNewsList.length>0">
<news-list :newsList="foreignNewsList" :header-title="'外媒'" @update:message="ReFlesh"></news-list>
</n-gi>

View File

@@ -1,6 +1,7 @@
<script setup>
import {ReFleshTelegraphList} from "../../wailsjs/go/main/App";
import {RefreshCircle, RefreshCircleSharp, RefreshOutline} from "@vicons/ionicons5";
import {computed, h, onBeforeMount, onBeforeUnmount, onMounted,onUnmounted, ref} from 'vue'
const { headerTitle,newsList } = defineProps({
headerTitle: {
@@ -18,6 +19,30 @@ const emits = defineEmits(['update:message'])
const updateMessage = () => {
emits('update:message', headerTitle)
}
// 使用 ref 创建响应式时间数据
const time = ref(new Date())
// 更新时间的函数
const updateTime = () => {
time.value = new Date()
}
let timer = null
// 组件挂载时启动定时器
onMounted(() => {
if (headerTitle === '财联社电报') {
// 每秒更新一次时间
timer = setInterval(updateTime, 1000)
}
})
// 组件卸载时清除定时器
onUnmounted(() => {
if (timer) {
clearInterval(timer)
}
})
</script>
<template>
@@ -25,17 +50,18 @@ const updateMessage = () => {
<template #header>
<n-flex justify="space-between">
<n-tag :bordered="false" size="large" type="success" >{{ headerTitle }}</n-tag>
<n-tag :bordered="false" size="large" type="info" v-if="headerTitle==='财联社电报'"> <n-time :time="time"/></n-tag>
<n-button :bordered="false" @click="updateMessage"><n-icon color="#409EFF" size="25" :component="RefreshCircleSharp"/></n-button>
</n-flex>
</template>
<n-list-item v-for="item in newsList">
<n-list-item v-for="(item,idx) in newsList" :key="item.ID">
<n-space justify="center" v-if="idx!==0 && item.dataTime.substring(0,10) !== newsList[idx-1].dataTime.substring(0,10)">
<n-divider>
{{ item.dataTime.substring(0,10) }}
</n-divider>
</n-space>
<n-space justify="start" >
<!-- <n-text justify="start" :bordered="false" :type="item.isRed?'error':'info'" style="overflow-wrap: break-word;">-->
<!-- <n-tag size="small" :type="item.isRed?'error':'warning'" :bordered="false"> {{ item.time }}</n-tag>-->
<!-- <n-text size="small" v-if="item.title" type="warning" :bordered="false">{{ item.title }}&nbsp;&nbsp;</n-text>-->
<!-- <n-text style="overflow-wrap: break-word;word-break: break-all; word-wrap: break-word;" :type="item.isRed?'error':'info'">{{ item.content }}</n-text>-->
<!-- </n-text>-->
<n-collapse v-if="item.title" arrow-placement="right">
<n-collapse v-if="item.title" arrow-placement="right" >
<n-collapse-item :name="item.title">
<template #header>
<n-tag size="small" :type="item.isRed?'error':'warning'" :bordered="false"> {{ item.time }}</n-tag>