This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// MpAutoReply 微信公众号自动回复表
|
||||
type MpAutoReply struct {
|
||||
global.GVA_MODEL
|
||||
Type int `json:"type" gorm:"not null;index;comment:回复类型 1关注回复 2消息回复 3关键字回复"`
|
||||
RequestKeyword *string `json:"requestKeyword" gorm:"type:varchar(255);index;comment:请求的关键字"`
|
||||
RequestMatch *int `json:"requestMatch" gorm:"comment:请求的关键字的匹配 1完全匹配 2半匹配"`
|
||||
RequestMessageType *string `json:"requestMessageType" gorm:"type:varchar(32);index;comment:请求的消息类型"`
|
||||
ResponseMessageType string `json:"responseMessageType" gorm:"type:varchar(32);not null;comment:回复的消息类型"`
|
||||
ResponseContent *string `json:"responseContent" gorm:"type:varchar(1024);comment:回复的消息内容"`
|
||||
ResponseMediaID *string `json:"responseMediaId" gorm:"type:varchar(128);comment:回复的媒体文件 id"`
|
||||
ResponseMediaURL *string `json:"responseMediaUrl" gorm:"type:varchar(1024);comment:回复的媒体文件 URL"`
|
||||
ResponseTitle *string `json:"responseTitle" gorm:"type:varchar(128);comment:回复的标题"`
|
||||
ResponseDescription *string `json:"responseDescription" gorm:"type:varchar(256);comment:回复的描述"`
|
||||
ResponseThumbMediaID *string `json:"responseThumbMediaId" gorm:"type:varchar(128);comment:回复的缩略图的媒体 id"`
|
||||
ResponseThumbMediaURL *string `json:"responseThumbMediaUrl" gorm:"type:varchar(1024);comment:回复的缩略图的媒体 URL"`
|
||||
ResponseArticles *string `json:"responseArticles" gorm:"type:varchar(1024);comment:回复的图文消息数组"`
|
||||
ResponseMusicURL *string `json:"responseMusicUrl" gorm:"type:varchar(1024);comment:回复的音乐链接"`
|
||||
ResponseHqMusicURL *string `json:"responseHqMusicUrl" gorm:"type:varchar(1024);comment:回复的高质量音乐链接"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpAutoReply) TableName() string {
|
||||
return "mp_auto_reply"
|
||||
}
|
||||
|
||||
// AutoReplyType 自动回复类型常量
|
||||
const (
|
||||
AutoReplyTypeSubscribe = 1 // 关注回复
|
||||
AutoReplyTypeMessage = 2 // 消息回复
|
||||
AutoReplyTypeKeyword = 3 // 关键字回复
|
||||
)
|
||||
|
||||
// MatchType 匹配类型常量
|
||||
const (
|
||||
MatchTypeExact = 1 // 完全匹配
|
||||
MatchTypePartial = 2 // 半匹配
|
||||
)
|
||||
|
||||
// IsSubscribeReply 是否为关注回复
|
||||
func (m *MpAutoReply) IsSubscribeReply() bool {
|
||||
return m.Type == AutoReplyTypeSubscribe
|
||||
}
|
||||
|
||||
// IsMessageReply 是否为消息回复
|
||||
func (m *MpAutoReply) IsMessageReply() bool {
|
||||
return m.Type == AutoReplyTypeMessage
|
||||
}
|
||||
|
||||
// IsKeywordReply 是否为关键字回复
|
||||
func (m *MpAutoReply) IsKeywordReply() bool {
|
||||
return m.Type == AutoReplyTypeKeyword
|
||||
}
|
||||
|
||||
// IsExactMatch 是否为完全匹配
|
||||
func (m *MpAutoReply) IsExactMatch() bool {
|
||||
return m.RequestMatch != nil && *m.RequestMatch == MatchTypeExact
|
||||
}
|
||||
|
||||
// IsPartialMatch 是否为部分匹配
|
||||
func (m *MpAutoReply) IsPartialMatch() bool {
|
||||
return m.RequestMatch != nil && *m.RequestMatch == MatchTypePartial
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// MpConfig 微信配置表
|
||||
type MpConfig struct {
|
||||
global.GVA_MODEL
|
||||
ConfigType string `json:"configType" gorm:"type:varchar(32);not null;index;comment:配置类型 mp公众号 mini小程序"`
|
||||
AppID string `json:"appId" gorm:"type:varchar(128);not null;comment:应用ID"`
|
||||
AppSecret string `json:"appSecret" gorm:"type:varchar(256);not null;comment:应用密钥"`
|
||||
Token *string `json:"token" gorm:"type:varchar(128);comment:Token"`
|
||||
EncodingAESKey *string `json:"encodingAESKey" gorm:"type:varchar(256);comment:消息加解密密钥"`
|
||||
|
||||
// 公众号特有配置
|
||||
ServerURL *string `json:"serverUrl" gorm:"type:varchar(512);comment:服务器地址"`
|
||||
WebhookURL *string `json:"webhookUrl" gorm:"type:varchar(512);comment:Webhook地址"`
|
||||
|
||||
// 小程序特有配置
|
||||
MiniAppName *string `json:"miniAppName" gorm:"type:varchar(128);comment:小程序名称"`
|
||||
MiniAppDesc *string `json:"miniAppDesc" gorm:"type:varchar(512);comment:小程序描述"`
|
||||
|
||||
// 状态信息
|
||||
Status string `json:"status" gorm:"type:varchar(32);default:'inactive';comment:状态 active激活 inactive未激活"`
|
||||
LastTestTime *time.Time `json:"lastTestTime" gorm:"comment:最后测试时间"`
|
||||
TestResult *string `json:"testResult" gorm:"type:varchar(512);comment:测试结果"`
|
||||
|
||||
// 扩展配置
|
||||
ExtraConfig *string `json:"extraConfig" gorm:"type:text;comment:扩展配置JSON"`
|
||||
Remark *string `json:"remark" gorm:"type:varchar(512);comment:备注"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpConfig) TableName() string {
|
||||
return "mp_config"
|
||||
}
|
||||
|
||||
// ConfigType 配置类型常量
|
||||
const (
|
||||
ConfigTypeMP = "mp" // 公众号
|
||||
ConfigTypeMini = "mini" // 小程序
|
||||
)
|
||||
|
||||
// Status 状态常量
|
||||
const (
|
||||
ConfigStatusActive = "active" // 激活
|
||||
ConfigStatusInactive = "inactive" // 未激活
|
||||
ConfigStatusError = "error" // 错误
|
||||
)
|
||||
|
||||
// IsMP 是否为公众号配置
|
||||
func (c *MpConfig) IsMP() bool {
|
||||
return c.ConfigType == ConfigTypeMP
|
||||
}
|
||||
|
||||
// IsMini 是否为小程序配置
|
||||
func (c *MpConfig) IsMini() bool {
|
||||
return c.ConfigType == ConfigTypeMini
|
||||
}
|
||||
|
||||
// IsActive 是否激活状态
|
||||
func (c *MpConfig) IsActive() bool {
|
||||
return c.Status == ConfigStatusActive
|
||||
}
|
||||
|
||||
// IsInactive 是否未激活状态
|
||||
func (c *MpConfig) IsInactive() bool {
|
||||
return c.Status == ConfigStatusInactive
|
||||
}
|
||||
|
||||
// IsError 是否错误状态
|
||||
func (c *MpConfig) IsError() bool {
|
||||
return c.Status == ConfigStatusError
|
||||
}
|
||||
|
||||
// GetDisplayName 获取显示名称
|
||||
func (c *MpConfig) GetDisplayName() string {
|
||||
if c.IsMP() {
|
||||
return "微信公众号"
|
||||
} else if c.IsMini() {
|
||||
if c.MiniAppName != nil && *c.MiniAppName != "" {
|
||||
return *c.MiniAppName
|
||||
}
|
||||
return "微信小程序"
|
||||
}
|
||||
return "未知类型"
|
||||
}
|
||||
|
||||
// MpWebhookLog 微信Webhook日志表
|
||||
type MpWebhookLog struct {
|
||||
global.GVA_MODEL
|
||||
ConfigID uint `json:"configId" gorm:"not null;index;comment:配置ID"`
|
||||
RequestURL string `json:"requestUrl" gorm:"type:varchar(512);not null;comment:请求URL"`
|
||||
RequestMethod string `json:"requestMethod" gorm:"type:varchar(16);not null;comment:请求方法"`
|
||||
RequestHeaders *string `json:"requestHeaders" gorm:"type:text;comment:请求头"`
|
||||
RequestBody *string `json:"requestBody" gorm:"type:text;comment:请求体"`
|
||||
ResponseStatus int `json:"responseStatus" gorm:"not null;comment:响应状态码"`
|
||||
ResponseBody *string `json:"responseBody" gorm:"type:text;comment:响应体"`
|
||||
ProcessTime int `json:"processTime" gorm:"not null;comment:处理时间(毫秒)"`
|
||||
ErrorMessage *string `json:"errorMessage" gorm:"type:varchar(512);comment:错误信息"`
|
||||
|
||||
// 微信相关字段
|
||||
Signature *string `json:"signature" gorm:"type:varchar(128);comment:微信签名"`
|
||||
Timestamp *string `json:"timestamp" gorm:"type:varchar(32);comment:时间戳"`
|
||||
Nonce *string `json:"nonce" gorm:"type:varchar(32);comment:随机数"`
|
||||
Echostr *string `json:"echostr" gorm:"type:varchar(128);comment:随机字符串"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpWebhookLog) TableName() string {
|
||||
return "mp_webhook_log"
|
||||
}
|
||||
|
||||
// IsSuccess 是否成功
|
||||
func (l *MpWebhookLog) IsSuccess() bool {
|
||||
return l.ResponseStatus >= 200 && l.ResponseStatus < 300
|
||||
}
|
||||
|
||||
// IsError 是否错误
|
||||
func (l *MpWebhookLog) IsError() bool {
|
||||
return l.ResponseStatus >= 400 || l.ErrorMessage != nil
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// MpDraft 微信公众号草稿表
|
||||
type MpDraft struct {
|
||||
global.GVA_MODEL
|
||||
MediaID string `json:"mediaId" gorm:"type:varchar(128);not null;index;comment:草稿的media_id"`
|
||||
Title string `json:"title" gorm:"type:varchar(255);not null;comment:图文消息标题"`
|
||||
Author *string `json:"author" gorm:"type:varchar(100);comment:作者"`
|
||||
Digest *string `json:"digest" gorm:"type:varchar(500);comment:图文消息摘要"`
|
||||
Content *string `json:"content" gorm:"type:longtext;comment:图文消息内容"`
|
||||
ContentSourceUrl *string `json:"contentSourceUrl" gorm:"type:varchar(1024);comment:原文地址"`
|
||||
ThumbMediaID *string `json:"thumbMediaId" gorm:"type:varchar(128);comment:缩略图的media_id"`
|
||||
ThumbUrl *string `json:"thumbUrl" gorm:"type:varchar(1024);comment:缩略图URL"`
|
||||
ShowCoverPic int `json:"showCoverPic" gorm:"default:1;comment:是否显示封面 0不显示 1显示"`
|
||||
NeedOpenComment int `json:"needOpenComment" gorm:"default:0;comment:是否打开评论 0不打开 1打开"`
|
||||
OnlyFansCanComment int `json:"onlyFansCanComment" gorm:"default:0;comment:是否粉丝才可评论 0所有人 1粉丝"`
|
||||
|
||||
// 草稿状态
|
||||
Status string `json:"status" gorm:"type:varchar(32);default:'draft';comment:状态 draft草稿 published已发布"`
|
||||
UpdateTime *time.Time `json:"updateTime" gorm:"comment:更新时间"`
|
||||
|
||||
// 微信相关
|
||||
WechatMediaID *string `json:"wechatMediaId" gorm:"type:varchar(128);comment:微信草稿media_id"`
|
||||
WechatCreateTime *time.Time `json:"wechatCreateTime" gorm:"comment:微信创建时间"`
|
||||
WechatUpdateTime *time.Time `json:"wechatUpdateTime" gorm:"comment:微信更新时间"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpDraft) TableName() string {
|
||||
return "mp_draft"
|
||||
}
|
||||
|
||||
// DraftStatus 草稿状态常量
|
||||
const (
|
||||
DraftStatusDraft = "draft" // 草稿
|
||||
DraftStatusPublished = "published" // 已发布
|
||||
DraftStatusDeleted = "deleted" // 已删除
|
||||
)
|
||||
|
||||
// IsDraft 是否为草稿状态
|
||||
func (d *MpDraft) IsDraft() bool {
|
||||
return d.Status == DraftStatusDraft
|
||||
}
|
||||
|
||||
// IsPublished 是否已发布
|
||||
func (d *MpDraft) IsPublished() bool {
|
||||
return d.Status == DraftStatusPublished
|
||||
}
|
||||
|
||||
// IsDeleted 是否已删除
|
||||
func (d *MpDraft) IsDeleted() bool {
|
||||
return d.Status == DraftStatusDeleted
|
||||
}
|
||||
|
||||
// GetDisplayTitle 获取显示标题
|
||||
func (d *MpDraft) GetDisplayTitle() string {
|
||||
if d.Title == "" {
|
||||
return "无标题"
|
||||
}
|
||||
return d.Title
|
||||
}
|
||||
|
||||
// GetDisplayAuthor 获取显示作者
|
||||
func (d *MpDraft) GetDisplayAuthor() string {
|
||||
if d.Author == nil || *d.Author == "" {
|
||||
return "未知作者"
|
||||
}
|
||||
return *d.Author
|
||||
}
|
||||
|
||||
// HasThumb 是否有缩略图
|
||||
func (d *MpDraft) HasThumb() bool {
|
||||
return d.ThumbMediaID != nil && *d.ThumbMediaID != ""
|
||||
}
|
||||
|
||||
// IsShowCover 是否显示封面
|
||||
func (d *MpDraft) IsShowCover() bool {
|
||||
return d.ShowCoverPic == 1
|
||||
}
|
||||
|
||||
// IsOpenComment 是否打开评论
|
||||
func (d *MpDraft) IsOpenComment() bool {
|
||||
return d.NeedOpenComment == 1
|
||||
}
|
||||
|
||||
// IsOnlyFansComment 是否仅粉丝可评论
|
||||
func (d *MpDraft) IsOnlyFansComment() bool {
|
||||
return d.OnlyFansCanComment == 1
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// MpMaterial 微信公众号素材表
|
||||
type MpMaterial struct {
|
||||
global.GVA_MODEL
|
||||
MediaID string `json:"mediaId" gorm:"type:varchar(128);not null;index;comment:公众号素材 id"`
|
||||
Type string `json:"type" gorm:"type:varchar(32);not null;index;comment:文件类型 image图片 voice语音 video视频 thumb缩略图"`
|
||||
Permanent bool `json:"permanent" gorm:"not null;default:false;index;comment:是否永久素材"`
|
||||
URL *string `json:"url" gorm:"type:varchar(1024);comment:文件服务器的 URL"`
|
||||
Name *string `json:"name" gorm:"type:varchar(255);comment:素材名字"`
|
||||
MpURL *string `json:"mpUrl" gorm:"type:varchar(1024);comment:公众号文件 URL"`
|
||||
Title *string `json:"title" gorm:"type:varchar(255);comment:视频素材的标题"`
|
||||
Introduction *string `json:"introduction" gorm:"type:varchar(255);comment:视频素材的描述"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpMaterial) TableName() string {
|
||||
return "mp_material"
|
||||
}
|
||||
|
||||
// MaterialType 素材类型常量
|
||||
const (
|
||||
MaterialTypeImage = "image" // 图片
|
||||
MaterialTypeVoice = "voice" // 语音
|
||||
MaterialTypeVideo = "video" // 视频
|
||||
MaterialTypeThumb = "thumb" // 缩略图
|
||||
MaterialTypeNews = "news" // 图文消息
|
||||
)
|
||||
|
||||
// IsImage 是否为图片素材
|
||||
func (m *MpMaterial) IsImage() bool {
|
||||
return m.Type == MaterialTypeImage
|
||||
}
|
||||
|
||||
// IsVoice 是否为语音素材
|
||||
func (m *MpMaterial) IsVoice() bool {
|
||||
return m.Type == MaterialTypeVoice
|
||||
}
|
||||
|
||||
// IsVideo 是否为视频素材
|
||||
func (m *MpMaterial) IsVideo() bool {
|
||||
return m.Type == MaterialTypeVideo
|
||||
}
|
||||
|
||||
// IsThumb 是否为缩略图素材
|
||||
func (m *MpMaterial) IsThumb() bool {
|
||||
return m.Type == MaterialTypeThumb
|
||||
}
|
||||
|
||||
// IsNews 是否为图文消息素材
|
||||
func (m *MpMaterial) IsNews() bool {
|
||||
return m.Type == MaterialTypeNews
|
||||
}
|
||||
|
||||
// IsPermanent 是否为永久素材
|
||||
func (m *MpMaterial) IsPermanent() bool {
|
||||
return m.Permanent
|
||||
}
|
||||
|
||||
// IsTemporary 是否为临时素材
|
||||
func (m *MpMaterial) IsTemporary() bool {
|
||||
return !m.Permanent
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// MpMenu 微信公众号菜单表
|
||||
type MpMenu struct {
|
||||
global.GVA_MODEL
|
||||
Name *string `json:"name" gorm:"type:varchar(255);comment:菜单名称"`
|
||||
MenuKey *string `json:"menuKey" gorm:"type:varchar(255);comment:菜单标识"`
|
||||
ParentID *string `json:"parentId" gorm:"type:varchar(32);index;comment:父ID"`
|
||||
Type string `json:"type" gorm:"type:varchar(32);not null;default:'';index;comment:按钮类型"`
|
||||
URL *string `json:"url" gorm:"type:varchar(500);comment:网页链接"`
|
||||
MiniProgramAppID *string `json:"miniProgramAppId" gorm:"type:varchar(32);comment:小程序appid"`
|
||||
MiniProgramPagePath *string `json:"miniProgramPagePath" gorm:"type:varchar(200);comment:小程序页面路径"`
|
||||
ReplyMessageType *string `json:"replyMessageType" gorm:"type:varchar(32);comment:消息类型"`
|
||||
ReplyContent *string `json:"replyContent" gorm:"type:varchar(1024);comment:回复的消息内容"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpMenu) TableName() string {
|
||||
return "mp_menu"
|
||||
}
|
||||
|
||||
// MenuType 菜单类型常量
|
||||
const (
|
||||
MenuTypeClick = "click" // 点击推事件
|
||||
MenuTypeView = "view" // 跳转URL
|
||||
MenuTypeScanCodePush = "scancode_push" // 扫码推事件
|
||||
MenuTypeScanCodeWaitMsg = "scancode_waitmsg" // 扫码推事件且弹出"消息接收中"提示框
|
||||
MenuTypePicSysPhoto = "pic_sysphoto" // 弹出系统拍照发图
|
||||
MenuTypePicPhotoOrAlbum = "pic_photo_or_album" // 弹出拍照或者相册发图
|
||||
MenuTypePicWeixin = "pic_weixin" // 弹出微信相册发图器
|
||||
MenuTypeLocationSelect = "location_select" // 弹出地理位置选择器
|
||||
MenuTypeMiniProgram = "miniprogram" // 小程序
|
||||
)
|
||||
|
||||
// IsClickType 是否为点击类型
|
||||
func (m *MpMenu) IsClickType() bool {
|
||||
return m.Type == MenuTypeClick
|
||||
}
|
||||
|
||||
// IsViewType 是否为跳转类型
|
||||
func (m *MpMenu) IsViewType() bool {
|
||||
return m.Type == MenuTypeView
|
||||
}
|
||||
|
||||
// IsMiniProgramType 是否为小程序类型
|
||||
func (m *MpMenu) IsMiniProgramType() bool {
|
||||
return m.Type == MenuTypeMiniProgram
|
||||
}
|
||||
|
||||
// HasParent 是否有父菜单
|
||||
func (m *MpMenu) HasParent() bool {
|
||||
return m.ParentID != nil && *m.ParentID != ""
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// MpMessage 微信公众号消息表
|
||||
type MpMessage struct {
|
||||
global.GVA_MODEL
|
||||
Type string `json:"type" gorm:"type:varchar(32);not null;index;comment:消息类型"`
|
||||
OpenID string `json:"openid" gorm:"type:varchar(100);not null;index;comment:用户openid"`
|
||||
InMsgID *string `json:"inMsgId" gorm:"type:varchar(64);comment:微信消息id"`
|
||||
Content *string `json:"content" gorm:"type:text;comment:消息内容"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpMessage) TableName() string {
|
||||
return "mp_message"
|
||||
}
|
||||
|
||||
// MessageType 消息类型常量
|
||||
const (
|
||||
MessageTypeText = "text" // 文本消息
|
||||
MessageTypeImage = "image" // 图片消息
|
||||
MessageTypeVoice = "voice" // 语音消息
|
||||
MessageTypeVideo = "video" // 视频消息
|
||||
MessageTypeMusic = "music" // 音乐消息
|
||||
MessageTypeNews = "news" // 图文消息
|
||||
MessageTypeLocation = "location" // 地理位置消息
|
||||
MessageTypeLink = "link" // 链接消息
|
||||
MessageTypeEvent = "event" // 事件消息
|
||||
)
|
||||
|
||||
// IsTextMessage 是否为文本消息
|
||||
func (m *MpMessage) IsTextMessage() bool {
|
||||
return m.Type == MessageTypeText
|
||||
}
|
||||
|
||||
// IsEventMessage 是否为事件消息
|
||||
func (m *MpMessage) IsEventMessage() bool {
|
||||
return m.Type == MessageTypeEvent
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// MpNews 微信公众号图文发表记录表
|
||||
type MpNews struct {
|
||||
global.GVA_MODEL
|
||||
MediaID string `json:"mediaId" gorm:"type:varchar(128);not null;index;comment:图文消息的media_id"`
|
||||
Title string `json:"title" gorm:"type:varchar(255);not null;comment:图文消息标题"`
|
||||
Author *string `json:"author" gorm:"type:varchar(100);comment:作者"`
|
||||
Digest *string `json:"digest" gorm:"type:varchar(500);comment:图文消息摘要"`
|
||||
Content *string `json:"content" gorm:"type:longtext;comment:图文消息内容"`
|
||||
ContentURL *string `json:"contentUrl" gorm:"type:varchar(1024);comment:图文页的URL"`
|
||||
SourceURL *string `json:"sourceUrl" gorm:"type:varchar(1024);comment:原文地址"`
|
||||
ThumbMediaID *string `json:"thumbMediaId" gorm:"type:varchar(128);comment:缩略图的media_id"`
|
||||
ThumbURL *string `json:"thumbUrl" gorm:"type:varchar(1024);comment:缩略图URL"`
|
||||
ShowCover bool `json:"showCover" gorm:"default:true;comment:是否显示封面"`
|
||||
NeedOpenComment bool `json:"needOpenComment" gorm:"default:false;comment:是否打开评论"`
|
||||
OnlyFansCanComment bool `json:"onlyFansCanComment" gorm:"default:false;comment:是否粉丝才可评论"`
|
||||
|
||||
// 发布信息
|
||||
PublishTime *time.Time `json:"publishTime" gorm:"comment:发布时间"`
|
||||
PublishStatus string `json:"publishStatus" gorm:"type:varchar(32);default:'draft';comment:发布状态 draft草稿 published已发布"`
|
||||
|
||||
// 统计数据
|
||||
ReadNum int `json:"readNum" gorm:"default:0;comment:阅读数"`
|
||||
LikeNum int `json:"likeNum" gorm:"default:0;comment:点赞数"`
|
||||
CommentNum int `json:"commentNum" gorm:"default:0;comment:评论数"`
|
||||
ShareNum int `json:"shareNum" gorm:"default:0;comment:分享数"`
|
||||
|
||||
// 微信相关
|
||||
WechatURL *string `json:"wechatUrl" gorm:"type:varchar(1024);comment:微信图文链接"`
|
||||
WechatMsgID *string `json:"wechatMsgId" gorm:"type:varchar(128);comment:微信消息ID"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpNews) TableName() string {
|
||||
return "mp_news"
|
||||
}
|
||||
|
||||
// PublishStatus 发布状态常量
|
||||
const (
|
||||
NewsStatusDraft = "draft" // 草稿
|
||||
NewsStatusPublished = "published" // 已发布
|
||||
NewsStatusDeleted = "deleted" // 已删除
|
||||
)
|
||||
|
||||
// IsDraft 是否为草稿状态
|
||||
func (n *MpNews) IsDraft() bool {
|
||||
return n.PublishStatus == NewsStatusDraft
|
||||
}
|
||||
|
||||
// IsPublished 是否已发布
|
||||
func (n *MpNews) IsPublished() bool {
|
||||
return n.PublishStatus == NewsStatusPublished
|
||||
}
|
||||
|
||||
// IsDeleted 是否已删除
|
||||
func (n *MpNews) IsDeleted() bool {
|
||||
return n.PublishStatus == NewsStatusDeleted
|
||||
}
|
||||
|
||||
// GetReadCount 获取阅读数
|
||||
func (n *MpNews) GetReadCount() int {
|
||||
return n.ReadNum
|
||||
}
|
||||
|
||||
// GetLikeCount 获取点赞数
|
||||
func (n *MpNews) GetLikeCount() int {
|
||||
return n.LikeNum
|
||||
}
|
||||
|
||||
// GetCommentCount 获取评论数
|
||||
func (n *MpNews) GetCommentCount() int {
|
||||
return n.CommentNum
|
||||
}
|
||||
|
||||
// GetShareCount 获取分享数
|
||||
func (n *MpNews) GetShareCount() int {
|
||||
return n.ShareNum
|
||||
}
|
||||
|
||||
// GetTotalInteraction 获取总互动数
|
||||
func (n *MpNews) GetTotalInteraction() int {
|
||||
return n.ReadNum + n.LikeNum + n.CommentNum + n.ShareNum
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// MpUser 微信公众号粉丝表 (增加用户关联字段)
|
||||
type MpUser struct {
|
||||
global.GVA_MODEL
|
||||
OpenID string `json:"openid" gorm:"type:varchar(100);not null;uniqueIndex;comment:用户openid"`
|
||||
UnionID *string `json:"unionid" gorm:"type:varchar(64);index;comment:微信开放平台统一标识"`
|
||||
UserID *uint `json:"userId" gorm:"index;comment:关联系统用户ID"`
|
||||
Nickname *string `json:"nickname" gorm:"type:varchar(50);comment:用户昵称"`
|
||||
HeadImageURL *string `json:"headImageUrl" gorm:"type:varchar(1024);comment:用户头像"`
|
||||
SubscribeStatus int `json:"subscribeStatus" gorm:"not null;index;comment:关注状态 0未关注 1已关注"`
|
||||
SubscribeTime *time.Time `json:"subscribeTime" gorm:"index;comment:关注时间"`
|
||||
UnsubscribeTime *time.Time `json:"unsubscribeTime" gorm:"comment:取消关注时间"`
|
||||
Language *string `json:"language" gorm:"type:varchar(30);comment:用户语言"`
|
||||
Country *string `json:"country" gorm:"type:varchar(30);comment:用户国家"`
|
||||
Province *string `json:"province" gorm:"type:varchar(30);comment:用户省份"`
|
||||
City *string `json:"city" gorm:"type:varchar(30);comment:用户城市"`
|
||||
Remark *string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
||||
TagIDs *string `json:"tagIds" gorm:"type:varchar(255);comment:标签编号数组"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (MpUser) TableName() string {
|
||||
return "mp_user"
|
||||
}
|
||||
|
||||
// IsSubscribed 检查是否已关注
|
||||
func (m *MpUser) IsSubscribed() bool {
|
||||
return m.SubscribeStatus == 1
|
||||
}
|
||||
|
||||
// Subscribe 关注操作
|
||||
func (m *MpUser) Subscribe() {
|
||||
m.SubscribeStatus = 1
|
||||
now := time.Now()
|
||||
m.SubscribeTime = &now
|
||||
m.UnsubscribeTime = nil
|
||||
}
|
||||
|
||||
// Unsubscribe 取消关注操作
|
||||
func (m *MpUser) Unsubscribe() {
|
||||
m.SubscribeStatus = 0
|
||||
now := time.Now()
|
||||
m.UnsubscribeTime = &now
|
||||
}
|
||||
|
||||
// IsLinkedToSystemUser 检查是否已关联系统用户
|
||||
func (m *MpUser) IsLinkedToSystemUser() bool {
|
||||
return m.UserID != nil && *m.UserID > 0
|
||||
}
|
||||
|
||||
// HasUnionID 检查是否有 UnionID
|
||||
func (m *MpUser) HasUnionID() bool {
|
||||
return m.UnionID != nil && *m.UnionID != ""
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package request
|
||||
|
||||
// MiniStatisticsRequest 小程序统计请求
|
||||
type MiniStatisticsRequest struct {
|
||||
StartDate string `json:"startDate" form:"startDate"` // 开始日期
|
||||
EndDate string `json:"endDate" form:"endDate"` // 结束日期
|
||||
Period string `json:"period" form:"period"` // 统计周期 day/week/month
|
||||
}
|
||||
|
||||
// VisitTrendRequest 访问趋势请求
|
||||
type VisitTrendRequest struct {
|
||||
StartDate string `json:"startDate" form:"startDate" binding:"required"` // 开始日期
|
||||
EndDate string `json:"endDate" form:"endDate" binding:"required"` // 结束日期
|
||||
}
|
||||
|
||||
// PageAnalysisRequest 页面分析请求
|
||||
type PageAnalysisRequest struct {
|
||||
StartDate string `json:"startDate" form:"startDate"` // 开始日期
|
||||
EndDate string `json:"endDate" form:"endDate"` // 结束日期
|
||||
PagePath string `json:"pagePath" form:"pagePath"` // 页面路径
|
||||
}
|
||||
|
||||
// UserRetentionRequest 用户留存请求
|
||||
type UserRetentionRequest struct {
|
||||
StartDate string `json:"startDate" form:"startDate" binding:"required"` // 开始日期
|
||||
EndDate string `json:"endDate" form:"endDate" binding:"required"` // 结束日期
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package request
|
||||
|
||||
// CreateAutoReplyRequest 创建自动回复请求
|
||||
type CreateAutoReplyRequest struct {
|
||||
Type int `json:"type" binding:"required" example:"1"`
|
||||
RequestKeyword string `json:"requestKeyword" example:"你好"`
|
||||
RequestMatch int `json:"requestMatch" example:"1"`
|
||||
RequestMessageType string `json:"requestMessageType" example:"text"`
|
||||
ResponseMessageType string `json:"responseMessageType" binding:"required" example:"text"`
|
||||
ResponseContent string `json:"responseContent" example:"欢迎关注我们的公众号"`
|
||||
ResponseMediaID string `json:"responseMediaId" example:""`
|
||||
ResponseMediaURL string `json:"responseMediaUrl" example:""`
|
||||
ResponseTitle string `json:"responseTitle" example:""`
|
||||
ResponseDescription string `json:"responseDescription" example:""`
|
||||
ResponseThumbMediaID string `json:"responseThumbMediaId" example:""`
|
||||
ResponseThumbMediaURL string `json:"responseThumbMediaUrl" example:""`
|
||||
ResponseArticles string `json:"responseArticles" example:""`
|
||||
ResponseMusicURL string `json:"responseMusicUrl" example:""`
|
||||
ResponseHqMusicURL string `json:"responseHqMusicUrl" example:""`
|
||||
}
|
||||
|
||||
// UpdateAutoReplyRequest 更新自动回复请求
|
||||
type UpdateAutoReplyRequest struct {
|
||||
ID uint `json:"id" binding:"required"`
|
||||
Type int `json:"type"`
|
||||
RequestKeyword string `json:"requestKeyword"`
|
||||
RequestMatch int `json:"requestMatch"`
|
||||
RequestMessageType string `json:"requestMessageType"`
|
||||
ResponseMessageType string `json:"responseMessageType"`
|
||||
ResponseContent string `json:"responseContent"`
|
||||
ResponseMediaID string `json:"responseMediaId"`
|
||||
ResponseMediaURL string `json:"responseMediaUrl"`
|
||||
ResponseTitle string `json:"responseTitle"`
|
||||
ResponseDescription string `json:"responseDescription"`
|
||||
ResponseThumbMediaID string `json:"responseThumbMediaId"`
|
||||
ResponseThumbMediaURL string `json:"responseThumbMediaUrl"`
|
||||
ResponseArticles string `json:"responseArticles"`
|
||||
ResponseMusicURL string `json:"responseMusicUrl"`
|
||||
ResponseHqMusicURL string `json:"responseHqMusicUrl"`
|
||||
}
|
||||
|
||||
// TestAutoReplyRequest 测试自动回复请求
|
||||
type TestAutoReplyRequest struct {
|
||||
Keyword string `json:"keyword" binding:"required" example:"你好"`
|
||||
}
|
||||
|
||||
// PageInfo 分页信息
|
||||
type PageInfo struct {
|
||||
Page int `json:"page" form:"page"` // 页码
|
||||
PageSize int `json:"pageSize" form:"pageSize"` // 每页数量
|
||||
}
|
||||
|
||||
// AutoReplyPageRequest 自动回复分页请求
|
||||
type AutoReplyPageRequest struct {
|
||||
PageInfo
|
||||
Type *int `json:"type" form:"type"`
|
||||
}
|
||||
|
||||
// SetSubscribeReplyRequest 设置关注回复请求
|
||||
type SetSubscribeReplyRequest struct {
|
||||
Content string `json:"content" binding:"required" example:"感谢您的关注!"`
|
||||
}
|
||||
|
||||
// SetKeywordReplyRequest 设置关键字回复请求
|
||||
type SetKeywordReplyRequest struct {
|
||||
Keyword string `json:"keyword" binding:"required" example:"你好"`
|
||||
Content string `json:"content" binding:"required" example:"您好,欢迎咨询!"`
|
||||
MatchType int `json:"matchType" binding:"required" example:"1"`
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package request
|
||||
|
||||
// CreateMenuRequest 创建菜单请求
|
||||
type CreateMenuRequest struct {
|
||||
Name string `json:"name" binding:"required" example:"菜单名称"`
|
||||
Type string `json:"type" binding:"required" example:"click"`
|
||||
ParentID string `json:"parentId" example:"1"`
|
||||
MenuKey string `json:"menuKey" example:"MENU_KEY_1"`
|
||||
URL string `json:"url" example:"https://example.com"`
|
||||
MiniProgramAppID string `json:"miniProgramAppId" example:"wx1234567890"`
|
||||
MiniProgramPagePath string `json:"miniProgramPagePath" example:"pages/index/index"`
|
||||
ReplyMessageType string `json:"replyMessageType" example:"text"`
|
||||
ReplyContent string `json:"replyContent" example:"欢迎使用"`
|
||||
}
|
||||
|
||||
// UpdateMenuRequest 更新菜单请求
|
||||
type UpdateMenuRequest struct {
|
||||
ID uint `json:"id" binding:"required"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
ParentID string `json:"parentId"`
|
||||
MenuKey string `json:"menuKey"`
|
||||
URL string `json:"url"`
|
||||
MiniProgramAppID string `json:"miniProgramAppId"`
|
||||
MiniProgramPagePath string `json:"miniProgramPagePath"`
|
||||
ReplyMessageType string `json:"replyMessageType"`
|
||||
ReplyContent string `json:"replyContent"`
|
||||
}
|
||||
|
||||
// MenuTreeNode 菜单树节点
|
||||
type MenuTreeNode struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
MenuKey string `json:"menuKey"`
|
||||
URL string `json:"url"`
|
||||
MiniProgramAppID string `json:"miniProgramAppId"`
|
||||
MiniProgramPagePath string `json:"miniProgramPagePath"`
|
||||
ReplyMessageType string `json:"replyMessageType"`
|
||||
ReplyContent string `json:"replyContent"`
|
||||
Children []MenuTreeNode `json:"children"`
|
||||
}
|
||||
|
||||
// SaveMenuRequest 保存菜单请求(批量保存)
|
||||
type SaveMenuRequest struct {
|
||||
Menus []CreateMenuRequest `json:"menus" binding:"required"`
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package request
|
||||
|
||||
// MiniLoginRequest 小程序登录请求
|
||||
type MiniLoginRequest struct {
|
||||
Code string `json:"code" binding:"required"` // 微信登录凭证
|
||||
}
|
||||
|
||||
// UpdateUserInfoRequest 更新用户信息请求
|
||||
type UpdateUserInfoRequest struct {
|
||||
OpenID string `json:"openid" binding:"required"` // 用户openid
|
||||
UserInfo map[string]interface{} `json:"userInfo"` // 用户信息
|
||||
}
|
||||
|
||||
// BindPhoneRequest 绑定手机号请求
|
||||
type BindPhoneRequest struct {
|
||||
OpenID string `json:"openid" binding:"required"` // 用户openid
|
||||
Phone string `json:"phone" binding:"required"` // 手机号
|
||||
}
|
||||
|
||||
// SyncUserRequest 同步用户请求
|
||||
type SyncUserRequest struct {
|
||||
OpenID string `json:"openid" binding:"required"` // 用户openid
|
||||
}
|
||||
|
||||
// UpdateRemarkRequest 更新备注请求
|
||||
type UpdateRemarkRequest struct {
|
||||
OpenID string `json:"openid" binding:"required"` // 用户openid
|
||||
Remark string `json:"remark"` // 备注内容
|
||||
}
|
||||
|
||||
// SendTextMessageRequest 发送文本消息请求
|
||||
type SendTextMessageRequest struct {
|
||||
OpenID string `json:"openid" binding:"required"` // 用户openid
|
||||
Content string `json:"content" binding:"required"` // 消息内容
|
||||
}
|
||||
|
||||
// SendImageMessageRequest 发送图片消息请求
|
||||
type SendImageMessageRequest struct {
|
||||
OpenID string `json:"openid" binding:"required"` // 用户openid
|
||||
MediaID string `json:"mediaId" binding:"required"` // 媒体ID
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package response
|
||||
|
||||
// MiniStatisticsResponse 小程序基础统计响应
|
||||
type MiniStatisticsResponse struct {
|
||||
TotalUsers int `json:"totalUsers"` // 总用户数
|
||||
ActiveUsers int `json:"activeUsers"` // 活跃用户数
|
||||
TotalSessions int `json:"totalSessions"` // 总会话数
|
||||
TodaySessions int `json:"todaySessions"` // 今日会话数
|
||||
TotalPV int `json:"totalPV"` // 总页面访问量
|
||||
TotalUV int `json:"totalUV"` // 总独立访客数
|
||||
AvgStayTime int `json:"avgStayTime"` // 平均停留时间(秒)
|
||||
BounceRate float64 `json:"bounceRate"` // 跳出率
|
||||
}
|
||||
|
||||
// VisitTrendData 访问趋势数据
|
||||
type VisitTrendData struct {
|
||||
Date string `json:"date"` // 日期
|
||||
SessionCnt int `json:"sessionCnt"` // 会话数
|
||||
VisitPV int `json:"visitPV"` // 页面访问量
|
||||
VisitUV int `json:"visitUV"` // 独立访客数
|
||||
VisitUVNew int `json:"visitUVNew"` // 新访客数
|
||||
StayTimeUV int `json:"stayTimeUV"` // 人均停留时长
|
||||
StayTimeSession int `json:"stayTimeSession"` // 次均停留时长
|
||||
}
|
||||
|
||||
// SourceData 用户来源数据
|
||||
type SourceData struct {
|
||||
RefType string `json:"refType"` // 来源类型
|
||||
Name string `json:"name"` // 来源名称
|
||||
SessionCnt int `json:"sessionCnt"` // 会话数
|
||||
VisitPV int `json:"visitPV"` // 页面访问量
|
||||
VisitUV int `json:"visitUV"` // 独立访客数
|
||||
Percentage float64 `json:"percentage"` // 占比
|
||||
}
|
||||
|
||||
// PageData 页面访问数据
|
||||
type PageData struct {
|
||||
PagePath string `json:"pagePath"` // 页面路径
|
||||
PageName string `json:"pageName"` // 页面名称
|
||||
PagePV int `json:"pagePV"` // 页面访问量
|
||||
PageUV int `json:"pageUV"` // 页面独立访客数
|
||||
StayTimePV int `json:"stayTimePV"` // 平均停留时长
|
||||
EntryPagePV int `json:"entryPagePV"` // 入口页次数
|
||||
ExitPagePV int `json:"exitPagePV"` // 退出页次数
|
||||
SharePV int `json:"sharePV"` // 转发次数
|
||||
ShareUV int `json:"shareUV"` // 转发人数
|
||||
}
|
||||
|
||||
// RetentionData 用户留存数据
|
||||
type RetentionData struct {
|
||||
RefDate string `json:"refDate"` // 日期
|
||||
VisitUVNew int `json:"visitUVNew"` // 新增用户数
|
||||
VisitUV int `json:"visitUV"` // 活跃用户数
|
||||
Day1 float64 `json:"day1"` // 1日留存率
|
||||
Day7 float64 `json:"day7"` // 7日留存率
|
||||
Day30 float64 `json:"day30"` // 30日留存率
|
||||
}
|
||||
|
||||
// DeviceData 设备数据
|
||||
type DeviceData struct {
|
||||
DeviceType string `json:"deviceType"` // 设备类型
|
||||
SessionCnt int `json:"sessionCnt"` // 会话数
|
||||
VisitUV int `json:"visitUV"` // 独立访客数
|
||||
Percentage float64 `json:"percentage"` // 占比
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package response
|
||||
|
||||
// MiniLoginResponse 小程序登录响应
|
||||
type MiniLoginResponse struct {
|
||||
OpenID string `json:"openid"` // 用户openid
|
||||
UnionID *string `json:"unionid"` // 用户unionid
|
||||
UserID *uint `json:"userId,omitempty"` // 关联的系统用户ID
|
||||
}
|
||||
|
||||
// PageResult 分页结果
|
||||
type PageResult struct {
|
||||
List interface{} `json:"list"` // 数据列表
|
||||
Total int64 `json:"total"` // 总数
|
||||
Page int `json:"page"` // 当前页
|
||||
PageSize int `json:"pageSize"` // 每页数量
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
)
|
||||
|
||||
// WechatMiniUser 微信小程序用户表
|
||||
type WechatMiniUser struct {
|
||||
global.GVA_MODEL
|
||||
OpenID string `json:"openid" gorm:"type:varchar(100);not null;uniqueIndex;comment:用户openid"`
|
||||
UnionID *string `json:"unionid" gorm:"type:varchar(64);index;comment:微信开放平台统一标识"`
|
||||
UserID *uint `json:"userId" gorm:"index;comment:关联系统用户ID"`
|
||||
SessionKey *string `json:"sessionKey" gorm:"type:varchar(255);comment:会话密钥"`
|
||||
Nickname *string `json:"nickname" gorm:"type:varchar(50);comment:用户昵称"`
|
||||
AvatarURL *string `json:"avatarUrl" gorm:"type:varchar(1024);comment:用户头像"`
|
||||
Gender *int `json:"gender" gorm:"comment:用户性别 0未知 1男 2女"`
|
||||
Country *string `json:"country" gorm:"type:varchar(30);comment:用户国家"`
|
||||
Province *string `json:"province" gorm:"type:varchar(30);comment:用户省份"`
|
||||
City *string `json:"city" gorm:"type:varchar(30);comment:用户城市"`
|
||||
Language *string `json:"language" gorm:"type:varchar(30);comment:用户语言"`
|
||||
Phone *string `json:"phone" gorm:"type:varchar(20);index;comment:手机号"`
|
||||
LastLoginTime *time.Time `json:"lastLoginTime" gorm:"comment:最后登录时间"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (WechatMiniUser) TableName() string {
|
||||
return "wechat_mini_users"
|
||||
}
|
||||
|
||||
// IsLinkedToSystemUser 检查是否已关联系统用户
|
||||
func (w *WechatMiniUser) IsLinkedToSystemUser() bool {
|
||||
return w.UserID != nil && *w.UserID > 0
|
||||
}
|
||||
|
||||
// HasUnionID 检查是否有 UnionID
|
||||
func (w *WechatMiniUser) HasUnionID() bool {
|
||||
return w.UnionID != nil && *w.UnionID != ""
|
||||
}
|
||||
|
||||
// HasPhone 检查是否已绑定手机号
|
||||
func (w *WechatMiniUser) HasPhone() bool {
|
||||
return w.Phone != nil && *w.Phone != ""
|
||||
}
|
||||
|
||||
// GetDisplayName 获取显示名称
|
||||
func (w *WechatMiniUser) GetDisplayName() string {
|
||||
if w.Nickname != nil && *w.Nickname != "" {
|
||||
return *w.Nickname
|
||||
}
|
||||
return "微信用户"
|
||||
}
|
||||
|
||||
// GetAvatarURL 获取头像URL
|
||||
func (w *WechatMiniUser) GetAvatarURL() string {
|
||||
if w.AvatarURL != nil {
|
||||
return *w.AvatarURL
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user