feat: 微信公众号技能包重命名(weixin_public_account)并增强功能
- 将 wechat_official_account 重命名为 weixin_public_account,符合中文命名规范 - 新增 DOCX 文档生成技能、聊天历史、请求 ID 中间件 - 增强工作流、热点服务、文章服务等模块功能 - 前端同步重命名组件和 API - 新增架构文档 AR13/AR14、专员文档更新 - 补充测试用例(seed_specialists_test, db_migration_test) Co-Authored-AI: yes
This commit is contained in:
+8
-8
@@ -5,14 +5,14 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
oaamodel "eai_agentplatform/backend/internal/specialists/packages/wechat_official_account/model"
|
||||
oaamodel "eai_agentplatform/backend/internal/specialists/packages/weixin_public_account/model"
|
||||
)
|
||||
|
||||
// OfficialAccountArticle 公众号文章状态仓库(一个任务一篇,task_id 上有唯一索引)。
|
||||
// WeixinPublicAccountArticle 公众号文章状态仓库(一个任务一篇,task_id 上有唯一索引)。
|
||||
//
|
||||
// 模型定义在专员技能包内(specialists/packages/wechat_official_account/model),
|
||||
// 模型定义在专员技能包内(specialists/packages/weixin_public_account/model),
|
||||
// 原先这个包自己拿 store.DB 读写,收口后统一走这里。
|
||||
type OfficialAccountArticleDAO struct{ *QueryBuilder }
|
||||
type WeixinPublicAccountArticleDAO struct{ *QueryBuilder }
|
||||
|
||||
// FindByTaskID 按任务取文章状态。三种结果,**调用方必须分清**:
|
||||
// - row != nil 找到了
|
||||
@@ -23,8 +23,8 @@ type OfficialAccountArticleDAO struct{ *QueryBuilder }
|
||||
// `if err == nil { return article }` 其余一律往下走新建 —— 也就是说读取
|
||||
// 真出错时也会去建一篇新的。task_id 上有唯一索引,这种误建多半会撞唯一键
|
||||
// 而失败,但那是运气不是设计。(同 UserXAppCenterDAO.FindByUser)
|
||||
func (r OfficialAccountArticleDAO) FindByTaskID(taskID uint) (*oaamodel.OfficialAccountArticle, error) {
|
||||
var row oaamodel.OfficialAccountArticle
|
||||
func (r WeixinPublicAccountArticleDAO) FindByTaskID(taskID uint) (*oaamodel.WeixinPublicAccountArticle, error) {
|
||||
var row oaamodel.WeixinPublicAccountArticle
|
||||
err := r.Inner().Where("task_id = ?", taskID).First(&row).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
@@ -36,11 +36,11 @@ func (r OfficialAccountArticleDAO) FindByTaskID(taskID uint) (*oaamodel.Official
|
||||
}
|
||||
|
||||
// Insert 新建文章状态。
|
||||
func (r OfficialAccountArticleDAO) Insert(a *oaamodel.OfficialAccountArticle) bool {
|
||||
func (r WeixinPublicAccountArticleDAO) Insert(a *oaamodel.WeixinPublicAccountArticle) bool {
|
||||
return r.QueryBuilder.Insert(a)
|
||||
}
|
||||
|
||||
// Update 保存文章状态(改标题/提纲/正文/配图等一律走这里)。
|
||||
func (r OfficialAccountArticleDAO) Update(a *oaamodel.OfficialAccountArticle) bool {
|
||||
func (r WeixinPublicAccountArticleDAO) Update(a *oaamodel.WeixinPublicAccountArticle) bool {
|
||||
return r.Save(a)
|
||||
}
|
||||
+7
-7
@@ -5,18 +5,18 @@ import (
|
||||
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
oahmodel "eai_agentplatform/backend/internal/specialists/packages/wechat_official_account/model"
|
||||
oahmodel "eai_agentplatform/backend/internal/specialists/packages/weixin_public_account/model"
|
||||
)
|
||||
|
||||
// OfficialAccountHotspot 公众号热点缓存仓库。
|
||||
// WeixinPublicAccountHotspot 公众号热点缓存仓库。
|
||||
//
|
||||
// 表里存的是抓取回来的 RSS/网页条目及其领域评分,按 (source_key, url)
|
||||
// 唯一,重复抓到同一条要就地更新而不是堆新行。
|
||||
type OfficialAccountHotspotDAO struct{ *QueryBuilder }
|
||||
type WeixinPublicAccountHotspotDAO struct{ *QueryBuilder }
|
||||
|
||||
// hotspotListLimit 单次取回的热点条数上限。
|
||||
//
|
||||
// 调用方(loadFreshOfficialAccountHotspots)取回后还要按关键词在内存里再滤一遍,
|
||||
// 调用方(loadFreshWeixinPublicAccountHotspots)取回后还要按关键词在内存里再滤一遍,
|
||||
// 所以这里多取一些留余量 —— 这个 40 是原实现写死的值,收口时原样保留。
|
||||
const hotspotListLimit = 40
|
||||
|
||||
@@ -33,8 +33,8 @@ const hotspotListLimit = 40
|
||||
// 调用方会走到不依赖热点的兜底选题路径。这个降级是有意接受的 ——
|
||||
// 数据访问层统一是 bool / 裸返回的风格(同 TaskRunDAO.ListByTask),
|
||||
// 不为一次缓存读再造一个 error 出口;但这是**行为变化**,不是等价重构。
|
||||
func (r OfficialAccountHotspotDAO) ListFresh(domainKey string, cutoff time.Time) []oahmodel.OfficialAccountHotspot {
|
||||
var items []oahmodel.OfficialAccountHotspot
|
||||
func (r WeixinPublicAccountHotspotDAO) ListFresh(domainKey string, cutoff time.Time) []oahmodel.WeixinPublicAccountHotspot {
|
||||
var items []oahmodel.WeixinPublicAccountHotspot
|
||||
if r.Type(&items).
|
||||
Where("business_domain = ? AND fetched_at >= ? AND domain_score > 0", domainKey, cutoff).
|
||||
Order("domain_score DESC, published_at DESC, id DESC").
|
||||
@@ -50,7 +50,7 @@ func (r OfficialAccountHotspotDAO) ListFresh(domainKey string, cutoff time.Time)
|
||||
// 这里返回 error 而不是 bool,是因为调用方要把 err.Error() 拼进给用户看的
|
||||
// 抓取日志(「热点入库失败:…」)——bool 装不下这句话,丢掉它用户就只看到
|
||||
// 「本轮未写入新热点」,无从知道是库的问题还是源站的问题。
|
||||
func (r OfficialAccountHotspotDAO) UpsertAll(rows []oahmodel.OfficialAccountHotspot) error {
|
||||
func (r WeixinPublicAccountHotspotDAO) UpsertAll(rows []oahmodel.WeixinPublicAccountHotspot) error {
|
||||
if len(rows) == 0 {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user