This commit is contained in:
2025-08-05 17:46:15 +08:00
parent e43d78ddf0
commit 4409bea9fc
106 changed files with 18564 additions and 7 deletions
@@ -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 ""
}