Files
pet-ai/server/plugin/wechat-integration/service/mp_draft_service.go
T
2025-08-06 09:02:16 +08:00

375 lines
11 KiB
Go

package service
import (
"errors"
"fmt"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/silenceper/wechat/v2/officialaccount"
"github.com/silenceper/wechat/v2/officialaccount/draft"
)
type MpDraftService struct{}
// DraftListResponse 草稿列表响应结构
type DraftListResponse struct {
Items []DraftItem `json:"items"`
TotalCount int `json:"totalCount"`
}
// DraftItem 草稿项目结构
type DraftItem struct {
MediaID string `json:"mediaId"`
Content DraftContent `json:"content"`
UpdateTime int64 `json:"updateTime"`
}
// DraftContent 草稿内容结构
type DraftContent struct {
NewsItem []DraftArticle `json:"newsItem"`
}
// DraftArticle 草稿文章结构
type DraftArticle struct {
Title string `json:"title"`
Author string `json:"author"`
Digest string `json:"digest"`
Content string `json:"content"`
ContentSourceURL string `json:"contentSourceUrl"`
ThumbMediaID string `json:"thumbMediaId"`
ShowCoverPic int `json:"showCoverPic"`
NeedOpenComment int `json:"needOpenComment"`
OnlyFansCanComment int `json:"onlyFansCanComment"`
ThumbURL string `json:"thumbUrl,omitempty"`
}
// GetDraftList 获取草稿列表
func (m *MpDraftService) GetDraftList(page, pageSize int, title, author string) (*DraftListResponse, error) {
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return nil, err
}
// 计算偏移量
offset := int64((page - 1) * pageSize)
count := int64(pageSize)
// 调用微信API获取草稿列表
draftService := oa.GetDraft()
articleList, err := draftService.PaginateDraft(offset, count, false)
if err != nil {
global.GVA_LOG.Error("获取微信草稿列表失败: " + err.Error())
return nil, fmt.Errorf("获取草稿列表失败: %v", err)
}
// 转换数据格式
response := &DraftListResponse{
Items: make([]DraftItem, 0, len(articleList.Item)),
TotalCount: int(articleList.TotalCount),
}
for _, item := range articleList.Item {
draftItem := DraftItem{
MediaID: item.MediaID,
UpdateTime: item.UpdateTime,
Content: DraftContent{
NewsItem: make([]DraftArticle, 0, len(item.Content.NewsItem)),
},
}
// 转换文章列表
for _, article := range item.Content.NewsItem {
draftArticle := DraftArticle{
Title: article.Title,
Author: article.Author,
Digest: article.Digest,
Content: article.Content,
ContentSourceURL: article.ContentSourceURL,
ThumbMediaID: article.ThumbMediaID,
ShowCoverPic: int(article.ShowCoverPic),
NeedOpenComment: int(article.NeedOpenComment),
OnlyFansCanComment: int(article.OnlyFansCanComment),
}
draftItem.Content.NewsItem = append(draftItem.Content.NewsItem, draftArticle)
}
// 应用过滤条件
if title != "" || author != "" {
matched := false
for _, article := range draftItem.Content.NewsItem {
if title != "" && article.Title != "" &&
len(article.Title) > 0 &&
article.Title == title {
matched = true
break
}
if author != "" && article.Author != "" &&
len(article.Author) > 0 &&
article.Author == author {
matched = true
break
}
}
if matched {
response.Items = append(response.Items, draftItem)
}
} else {
response.Items = append(response.Items, draftItem)
}
}
global.GVA_LOG.Info(fmt.Sprintf("成功获取草稿列表,共 %d 条记录", len(response.Items)))
return response, nil
}
// getOfficialAccount 获取微信公众号实例
func (m *MpDraftService) getOfficialAccount() (*officialaccount.OfficialAccount, error) {
// 使用用户服务获取公众号实例
mpUserService := &MpUserService{}
return mpUserService.GetOfficialAccount()
}
// GetDraftInfo 获取草稿详情(通过MediaID)
func (m *MpDraftService) GetDraftInfo(mediaID string) (*DraftItem, error) {
if mediaID == "" {
return nil, errors.New("MediaID不能为空")
}
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return nil, err
}
// 调用微信API获取草稿详情
draftService := oa.GetDraft()
articles, err := draftService.GetDraft(mediaID)
if err != nil {
global.GVA_LOG.Error("获取微信草稿详情失败: " + err.Error())
return nil, fmt.Errorf("获取草稿详情失败: %v", err)
}
// 转换数据格式
draftItem := &DraftItem{
MediaID: mediaID,
UpdateTime: 0, // 微信API返回的草稿详情不包含更新时间,需要从列表接口获取
Content: DraftContent{
NewsItem: make([]DraftArticle, 0, len(articles)),
},
}
// 转换文章列表
for _, article := range articles {
draftArticle := DraftArticle{
Title: article.Title,
Author: article.Author,
Digest: article.Digest,
Content: article.Content,
ContentSourceURL: article.ContentSourceURL,
ThumbMediaID: article.ThumbMediaID,
ShowCoverPic: int(article.ShowCoverPic),
NeedOpenComment: int(article.NeedOpenComment),
OnlyFansCanComment: int(article.OnlyFansCanComment),
}
draftItem.Content.NewsItem = append(draftItem.Content.NewsItem, draftArticle)
}
global.GVA_LOG.Info(fmt.Sprintf("成功获取草稿详情,MediaID: %s", mediaID))
return draftItem, nil
}
// CreateDraftRequest 创建草稿请求结构
type CreateDraftRequest struct {
Articles []DraftArticle `json:"articles"`
}
// CreateDraft 创建草稿
func (m *MpDraftService) CreateDraft(req *CreateDraftRequest) (string, error) {
if len(req.Articles) == 0 {
return "", errors.New("文章列表不能为空")
}
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return "", err
}
// 构建微信API请求参数
articles := make([]*draft.Article, 0, len(req.Articles))
for _, article := range req.Articles {
if article.Title == "" {
return "", errors.New("文章标题不能为空")
}
wxArticle := &draft.Article{
Title: article.Title,
Author: article.Author,
Digest: article.Digest,
Content: article.Content,
ContentSourceURL: article.ContentSourceURL,
ThumbMediaID: article.ThumbMediaID,
ShowCoverPic: uint(article.ShowCoverPic),
NeedOpenComment: uint(article.NeedOpenComment),
OnlyFansCanComment: uint(article.OnlyFansCanComment),
}
articles = append(articles, wxArticle)
}
// 调用微信API创建草稿
draftService := oa.GetDraft()
mediaID, err := draftService.AddDraft(articles)
if err != nil {
global.GVA_LOG.Error("创建微信草稿失败: " + err.Error())
return "", fmt.Errorf("创建草稿失败: %v", err)
}
return mediaID, nil
}
// UpdateDraftRequest 更新草稿请求结构
type UpdateDraftRequest struct {
MediaID string `json:"mediaId"`
Index int `json:"index"`
Articles []DraftArticle `json:"articles"`
}
// UpdateDraft 更新草稿
func (m *MpDraftService) UpdateDraft(req *UpdateDraftRequest) error {
if req.MediaID == "" {
return errors.New("草稿MediaID不能为空")
}
if len(req.Articles) == 0 {
return errors.New("文章列表不能为空")
}
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return err
}
// 微信API只支持单篇文章更新,需要逐个更新
draftService := oa.GetDraft()
for i, article := range req.Articles {
if article.Title == "" {
return fmt.Errorf("第%d篇文章标题不能为空", i+1)
}
wxArticle := &draft.Article{
Title: article.Title,
Author: article.Author,
Digest: article.Digest,
Content: article.Content,
ContentSourceURL: article.ContentSourceURL,
ThumbMediaID: article.ThumbMediaID,
ShowCoverPic: uint(article.ShowCoverPic),
NeedOpenComment: uint(article.NeedOpenComment),
OnlyFansCanComment: uint(article.OnlyFansCanComment),
}
// 调用微信API更新草稿
err = draftService.UpdateDraft(wxArticle, req.MediaID, uint(i))
if err != nil {
global.GVA_LOG.Error(fmt.Sprintf("更新草稿第%d篇文章失败: %s", i+1, err.Error()))
return fmt.Errorf("更新草稿第%d篇文章失败: %v", i+1, err)
}
}
global.GVA_LOG.Info(fmt.Sprintf("成功更新草稿,MediaID: %s,共更新 %d 篇文章", req.MediaID, len(req.Articles)))
return nil
}
// DeleteDraft 删除草稿
func (m *MpDraftService) DeleteDraft(mediaID string) error {
if mediaID == "" {
return errors.New("草稿MediaID不能为空")
}
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return err
}
// 调用微信API删除草稿
draftService := oa.GetDraft()
err = draftService.DeleteDraft(mediaID)
if err != nil {
global.GVA_LOG.Error("删除微信草稿失败: " + err.Error())
return fmt.Errorf("删除草稿失败: %v", err)
}
return nil
}
// PublishDraft 发布草稿
func (m *MpDraftService) PublishDraft(mediaID string) error {
if mediaID == "" {
return errors.New("草稿MediaID不能为空")
}
// 获取微信公众号实例
_, err := m.getOfficialAccount()
if err != nil {
return err
}
// 注意:微信公众号草稿发布需要使用freepublish模块
// 这里我们先记录日志,实际发布功能需要使用freepublish.SubmitPublish
global.GVA_LOG.Info(fmt.Sprintf("草稿发布请求,MediaID: %s。注意:实际发布需要使用freepublish模块", mediaID))
// 由于草稿发布涉及到发布流程,这里暂时只做记录
// 实际项目中可以调用 oa.GetFreePublish().SubmitPublish(mediaID) 来发布
return fmt.Errorf("草稿发布功能需要使用freepublish模块,MediaID: %s", mediaID)
}
// SyncDrafts 同步草稿
func (m *MpDraftService) SyncDrafts() error {
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return err
}
// 获取草稿总数
draftService := oa.GetDraft()
total, err := draftService.CountDraft()
if err != nil {
global.GVA_LOG.Error("获取草稿总数失败: " + err.Error())
return fmt.Errorf("同步草稿失败: %v", err)
}
global.GVA_LOG.Info(fmt.Sprintf("草稿同步完成,当前草稿总数: %d", total))
return nil
}
// GetDraftCount 获取草稿数量统计
func (m *MpDraftService) GetDraftCount() (map[string]int64, error) {
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return nil, err
}
// 调用微信API获取草稿总数
draftService := oa.GetDraft()
total, err := draftService.CountDraft()
if err != nil {
global.GVA_LOG.Error("获取草稿总数失败: " + err.Error())
return nil, fmt.Errorf("获取草稿数量失败: %v", err)
}
result := map[string]int64{
"draft": int64(total),
"published": 0, // 发布数量需要通过其他API获取
"total": int64(total),
}
global.GVA_LOG.Info(fmt.Sprintf("成功获取草稿数量统计,总数: %d", total))
return result, nil
}