完善文案的状态流转
This commit is contained in:
@@ -27,7 +27,7 @@ xhs:
|
|||||||
python_service_url: "http://localhost:8000" # Python服务地址
|
python_service_url: "http://localhost:8000" # Python服务地址
|
||||||
|
|
||||||
scheduler:
|
scheduler:
|
||||||
enabled: true # 是否启用定时任务
|
enabled: false # 是否启用定时任务
|
||||||
publish_cron: "* * * * * *" # 每1小时执行一次(开发环境测试用)
|
publish_cron: "* * * * * *" # 每1小时执行一次(开发环境测试用)
|
||||||
max_concurrent: 2 # 最大并发发布数
|
max_concurrent: 2 # 最大并发发布数
|
||||||
publish_timeout: 300 # 发布超时时间(秒)
|
publish_timeout: 300 # 发布超时时间(秒)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ xhs:
|
|||||||
python_service_url: "http://localhost:8000" # Python服务地址,生产环境请修改为实际地址
|
python_service_url: "http://localhost:8000" # Python服务地址,生产环境请修改为实际地址
|
||||||
|
|
||||||
scheduler:
|
scheduler:
|
||||||
enabled: true # 是否启用定时任务
|
enabled: false # 是否启用定时任务
|
||||||
publish_cron: "0 0 */2 * * *" # 每2小时执行一次(防封号策略)
|
publish_cron: "0 0 */2 * * *" # 每2小时执行一次(防封号策略)
|
||||||
max_concurrent: 2 # 最大并发发布数
|
max_concurrent: 2 # 最大并发发布数
|
||||||
publish_timeout: 300 # 发布超时时间(秒)
|
publish_timeout: 300 # 发布超时时间(秒)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EmployeeController struct {
|
type EmployeeController struct {
|
||||||
service *service.EmployeeService
|
service *service.EmployeeService
|
||||||
}
|
}
|
||||||
@@ -255,3 +256,41 @@ func (ctrl *EmployeeController) GetProducts(c *gin.Context) {
|
|||||||
"list": data,
|
"list": data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateArticleStatus 更新文案状态(通过/拒绝)
|
||||||
|
func (ctrl *EmployeeController) UpdateArticleStatus(c *gin.Context) {
|
||||||
|
employeeID := c.GetInt("employee_id")
|
||||||
|
articleID, err := strconv.Atoi(c.Param("id"))
|
||||||
|
if err != nil {
|
||||||
|
common.Error(c, common.CodeInvalidParams, "文案ID参数错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req struct {
|
||||||
|
Status string `json:"status" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证status值
|
||||||
|
if req.Status != "approved" && req.Status != "rejected" {
|
||||||
|
common.Error(c, common.CodeInvalidParams, "status只能为approved或rejected")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctrl.service.UpdateArticleStatus(employeeID, articleID, req.Status)
|
||||||
|
if err != nil {
|
||||||
|
common.Error(c, common.CodeInternalError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
message := "已通过"
|
||||||
|
if req.Status == "rejected" {
|
||||||
|
message = "已拒绝"
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SuccessWithMessage(c, message, nil)
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ func AutoMigrate() error {
|
|||||||
&models.PublishRecord{},
|
&models.PublishRecord{},
|
||||||
&models.ArticleImage{},
|
&models.ArticleImage{},
|
||||||
&models.ArticleTag{},
|
&models.ArticleTag{},
|
||||||
|
&models.Author{},
|
||||||
&models.Log{},
|
&models.Log{},
|
||||||
// &models.XHSAccount{}, // 不再使用,小红书信息直接存储在 ai_users 表中
|
// &models.XHSAccount{}, // 不再使用,小红书信息直接存储在 ai_users 表中
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,24 +6,25 @@ import (
|
|||||||
|
|
||||||
// Enterprise 企业表
|
// Enterprise 企业表
|
||||||
type Enterprise struct {
|
type Enterprise struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
EnterpriseID string `gorm:"type:varchar(255);not null;default:''" json:"enterprise_id" comment:"企业ID"`
|
EnterpriseID string `gorm:"type:varchar(255);not null;default:''" json:"enterprise_id" comment:"企业ID"`
|
||||||
Name string `gorm:"type:varchar(200);not null;default:''" json:"name" comment:"企业名称"`
|
Name string `gorm:"type:varchar(200);not null;default:''" json:"name" comment:"企业名称"`
|
||||||
ShortName string `gorm:"type:varchar(100);not null;default:''" json:"short_name" comment:"企业简称"`
|
ShortName string `gorm:"type:varchar(100);not null;default:''" json:"short_name" comment:"企业简称"`
|
||||||
Icon string `gorm:"type:varchar(500);not null;default:''" json:"icon" comment:"企业图标URL"`
|
Icon string `gorm:"type:varchar(500);not null;default:''" json:"icon" comment:"企业图标URL"`
|
||||||
Phone string `gorm:"type:varchar(20);not null;default:'';uniqueIndex:uk_phone" json:"phone" comment:"登录手机号"`
|
Phone string `gorm:"type:varchar(20);not null;default:'';uniqueIndex:uk_phone" json:"phone" comment:"登录手机号"`
|
||||||
Password string `gorm:"type:varchar(255);not null;default:''" json:"-" comment:"登录密码(加密存储)"`
|
Password string `gorm:"type:varchar(255);not null;default:''" json:"-" comment:"登录密码(加密存储)"`
|
||||||
Email string `gorm:"type:varchar(128);not null;default:''" json:"email" comment:"企业邮箱"`
|
Email string `gorm:"type:varchar(128);not null;default:''" json:"email" comment:"企业邮箱"`
|
||||||
Website string `gorm:"type:varchar(255);not null;default:''" json:"website" comment:"企业网站"`
|
Website string `gorm:"type:varchar(255);not null;default:''" json:"website" comment:"企业网站"`
|
||||||
Address string `gorm:"type:varchar(255);not null;default:''" json:"address" comment:"企业地址"`
|
Address string `gorm:"type:varchar(255);not null;default:''" json:"address" comment:"企业地址"`
|
||||||
Status string `gorm:"type:enum('active','disabled');not null;default:'active';index:idx_status" json:"status" comment:"状态"`
|
Status string `gorm:"type:enum('active','disabled');not null;default:'active';index:idx_status" json:"status" comment:"状态"`
|
||||||
UsersTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"users_total" comment:"员工总数"`
|
UsersTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"users_total" comment:"员工总数"`
|
||||||
ProductsTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"products_total" comment:"产品总数"`
|
ProductsTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"products_total" comment:"产品总数"`
|
||||||
ArticlesTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"articles_total" comment:"文章总数"`
|
PublishedTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"published_total" comment:"文章发布总数"`
|
||||||
ReleasedMonthTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"released_month_total" comment:"本月发布数量"`
|
ArticlesTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"articles_total" comment:"文章总数"`
|
||||||
LinkedToXHSNum int `gorm:"type:int(10) unsigned;not null;default:0" json:"linked_to_xhs_num" comment:"绑定小红书"`
|
ReleasedMonthTotal int `gorm:"type:int(10) unsigned;not null;default:0" json:"released_month_total" comment:"本月发布数量"`
|
||||||
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
LinkedToXHSNum int `gorm:"type:int(10) unsigned;not null;default:0" json:"linked_to_xhs_num" comment:"绑定小红书"`
|
||||||
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// User 用户账号表(原Employee,对应ai_users)
|
// User 用户账号表(原Employee,对应ai_users)
|
||||||
@@ -37,15 +38,15 @@ type User struct {
|
|||||||
RealName string `gorm:"type:varchar(50)" json:"real_name" comment:"真实姓名"`
|
RealName string `gorm:"type:varchar(50)" json:"real_name" comment:"真实姓名"`
|
||||||
Email string `gorm:"type:varchar(100)" json:"email" comment:"邮箱"`
|
Email string `gorm:"type:varchar(100)" json:"email" comment:"邮箱"`
|
||||||
Phone string `gorm:"type:varchar(20)" json:"phone" comment:"手机号"`
|
Phone string `gorm:"type:varchar(20)" json:"phone" comment:"手机号"`
|
||||||
WechatOpenID *string `gorm:"type:varchar(100);uniqueIndex:uk_wechat_openid" json:"wechat_openid,omitempty" comment:"微信OpenID"`
|
WechatOpenID *string `gorm:"column:wechat_openid;type:varchar(100);uniqueIndex:uk_wechat_openid" json:"wechat_openid,omitempty" comment:"微信OpenID"`
|
||||||
WechatUnionID *string `gorm:"type:varchar(100)" json:"wechat_unionid,omitempty" comment:"微信UnionID"`
|
WechatUnionID *string `gorm:"column:wechat_unionid;type:varchar(100)" json:"wechat_unionid,omitempty" comment:"微信UnionID"`
|
||||||
XHSPhone string `gorm:"type:varchar(20);not null;default:''" json:"xhs_phone" comment:"小红书绑定手机号"`
|
XHSPhone string `gorm:"type:varchar(20);not null;default:''" json:"xhs_phone" comment:"小红书绑定手机号"`
|
||||||
XHSAccount string `gorm:"type:varchar(255);not null;default:''" json:"xhs_account" comment:"小红书账号名称"`
|
XHSAccount string `gorm:"type:varchar(255);not null;default:''" json:"xhs_account" comment:"小红书账号名称"`
|
||||||
XHSCookie string `gorm:"type:text" json:"xhs_cookie" comment:"小红书Cookie"`
|
XHSCookie string `gorm:"type:text" json:"xhs_cookie" comment:"小红书Cookie"`
|
||||||
IsBoundXHS int `gorm:"type:tinyint(1);not null;default:0;index:idx_is_bound_xhs" json:"is_bound_xhs" comment:"是否绑定小红书:0=未绑定,1=已绑定"`
|
IsBoundXHS int `gorm:"type:tinyint(1);not null;default:0;index:idx_is_bound_xhs" json:"is_bound_xhs" comment:"是否绑定小红书:0=未绑定,1=已绑定"`
|
||||||
BoundAt *time.Time `json:"bound_at" comment:"绑定小红书的时间"`
|
BoundAt *time.Time `json:"bound_at" comment:"绑定小红书的时间"`
|
||||||
Department string `gorm:"type:varchar(50)" json:"department" comment:"部门"`
|
Department string `gorm:"type:varchar(50)" json:"department" comment:"部门"`
|
||||||
Role string `gorm:"type:enum('admin','editor','reviewer','publisher','each_title_reviewer');default:'editor'" json:"role" comment:"角色"`
|
Role string `gorm:"type:enum('admin','editor','reviewer','publisher','each_title_reviewer','enterprise');default:'editor'" json:"role" comment:"角色"`
|
||||||
Status string `gorm:"type:enum('active','inactive','deleted');default:'active';index:idx_status" json:"status" comment:"状态"`
|
Status string `gorm:"type:enum('active','inactive','deleted');default:'active';index:idx_status" json:"status" comment:"状态"`
|
||||||
CreatedAt time.Time `json:"created_at" comment:"创建时间"`
|
CreatedAt time.Time `json:"created_at" comment:"创建时间"`
|
||||||
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
||||||
@@ -59,6 +60,7 @@ type Product struct {
|
|||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
Name string `gorm:"type:varchar(200);not null;default:''" json:"name" comment:"产品名称"`
|
Name string `gorm:"type:varchar(200);not null;default:''" json:"name" comment:"产品名称"`
|
||||||
|
TypeID int `gorm:"type:int unsigned;not null;default:0" json:"type_id" comment:"type_id类型ID"`
|
||||||
TypeName string `gorm:"type:varchar(128);not null;default:''" json:"type_name" comment:"产品类型"`
|
TypeName string `gorm:"type:varchar(128);not null;default:''" json:"type_name" comment:"产品类型"`
|
||||||
ImageURL string `gorm:"type:varchar(500);not null;default:''" json:"image_url" comment:"产品主图URL"`
|
ImageURL string `gorm:"type:varchar(500);not null;default:''" json:"image_url" comment:"产品主图URL"`
|
||||||
ImageThumbnailURL string `gorm:"type:varchar(500);not null;default:''" json:"image_thumbnail_url" comment:"缩略图URL"`
|
ImageThumbnailURL string `gorm:"type:varchar(500);not null;default:''" json:"image_thumbnail_url" comment:"缩略图URL"`
|
||||||
@@ -72,35 +74,35 @@ type Product struct {
|
|||||||
|
|
||||||
// Article 文章表(原Copy,对应ai_articles)
|
// Article 文章表(原Copy,对应ai_articles)
|
||||||
type Article struct {
|
type Article struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
BatchID uint64 `gorm:"type:bigint unsigned;not null;default:0" json:"batch_id" comment:"批次ID"`
|
BatchID uint64 `gorm:"type:bigint unsigned;not null;default:0" json:"batch_id" comment:"批次ID"`
|
||||||
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
ProductID int `gorm:"not null;default:0;index:idx_product_id" json:"product_id" comment:"关联产品ID"`
|
ProductID int `gorm:"not null;default:0;index:idx_product_id" json:"product_id" comment:"关联产品ID"`
|
||||||
TopicTypeID int `gorm:"type:int unsigned;not null;default:0" json:"topic_type_id" comment:"topic类型ID"`
|
TopicTypeID int `gorm:"type:int unsigned;not null;default:0" json:"topic_type_id" comment:"topic类型ID"`
|
||||||
PromptWorkflowID int `gorm:"type:int unsigned;not null;default:0" json:"prompt_workflow_id" comment:"提示词工作流ID"`
|
PromptWorkflowID int `gorm:"type:int unsigned;not null;default:0" json:"prompt_workflow_id" comment:"提示词工作流ID"`
|
||||||
Topic string `gorm:"type:varchar(255);not null;default:''" json:"topic" comment:"topic主题"`
|
Topic string `gorm:"type:varchar(255);not null;default:''" json:"topic" comment:"topic主题"`
|
||||||
Title string `gorm:"type:varchar(200);not null;default:''" json:"title" comment:"标题"`
|
Title string `gorm:"type:varchar(200);not null;default:''" json:"title" comment:"标题"`
|
||||||
Content string `gorm:"type:text" json:"content" comment:"文章内容"`
|
Content string `gorm:"type:text" json:"content" comment:"文章内容"`
|
||||||
Department string `gorm:"type:varchar(255);not null;default:''" json:"department" comment:"部门"`
|
Department string `gorm:"type:varchar(255);not null;default:''" json:"department" comment:"部门"`
|
||||||
DepartmentIDs string `gorm:"column:departmentids;type:varchar(255);not null;default:''" json:"department_ids" comment:"部门IDs"`
|
DepartmentIDs string `gorm:"column:departmentids;type:varchar(255);not null;default:''" json:"department_ids" comment:"部门IDs"`
|
||||||
AuthorID *int `json:"author_id" comment:"作者ID"`
|
AuthorID *int `json:"author_id" comment:"作者ID"`
|
||||||
AuthorName string `gorm:"type:varchar(100)" json:"author_name" comment:"作者名称"`
|
AuthorName string `gorm:"type:varchar(100)" json:"author_name" comment:"作者名称"`
|
||||||
DepartmentID *int `json:"department_id" comment:"部门ID"`
|
DepartmentID *int `json:"department_id" comment:"部门ID"`
|
||||||
DepartmentName string `gorm:"type:varchar(255)" json:"department_name" comment:"部门名称"`
|
DepartmentName string `gorm:"type:varchar(255)" json:"department_name" comment:"部门名称"`
|
||||||
CreatedUserID int `gorm:"not null;default:0" json:"created_user_id" comment:"创建用户ID"`
|
CreatedUserID int `gorm:"not null;default:0" json:"created_user_id" comment:"创建用户ID"`
|
||||||
ReviewUserID *int `json:"review_user_id" comment:"审核用户ID"`
|
ReviewUserID *int `json:"review_user_id" comment:"审核用户ID"`
|
||||||
PublishUserID *int `json:"publish_user_id" comment:"发布用户ID"`
|
PublishUserID *int `json:"publish_user_id" comment:"发布用户ID"`
|
||||||
Status string `gorm:"type:enum('topic','cover_image','generate','generate_failed','draft','pending_review','approved','rejected','published_review','published','failed');default:'draft';index:idx_status" json:"status" comment:"状态"`
|
Status string `gorm:"type:enum('topic','cover_image','generate','generate_failed','draft','pending_review','assign_authors','approved','rejected','published_review','published','failed');default:'draft';index:idx_status" json:"status" comment:"状态"`
|
||||||
Channel int `gorm:"type:tinyint(1);not null;default:1" json:"channel" comment:"渠道:1=baidu|2=toutiao|3=weixin"`
|
Channel int `gorm:"type:tinyint(1);not null;default:1" json:"channel" comment:"渠道:1=baidu|2=toutiao|3=weixin"`
|
||||||
ReviewComment string `gorm:"type:text" json:"review_comment" comment:"审核评论"`
|
ReviewComment string `gorm:"type:text" json:"review_comment" comment:"审核评论"`
|
||||||
PublishTime *time.Time `json:"publish_time" comment:"发布时间"`
|
PublishTime *time.Time `json:"publish_time" comment:"发布时间"`
|
||||||
BaijiahaoID string `gorm:"type:varchar(100)" json:"baijiahao_id" comment:"百家号ID"`
|
BaijiahaoID string `gorm:"type:varchar(100)" json:"baijiahao_id" comment:"百家号ID"`
|
||||||
BaijiahaoStatus string `gorm:"type:varchar(50)" json:"baijiahao_status" comment:"百家号状态"`
|
BaijiahaoStatus string `gorm:"type:varchar(50)" json:"baijiahao_status" comment:"百家号状态"`
|
||||||
WordCount int `gorm:"default:0" json:"word_count" comment:"字数统计"`
|
WordCount int `gorm:"default:0" json:"word_count" comment:"字数统计"`
|
||||||
ImageCount int `gorm:"default:0" json:"image_count" comment:"图片数量"`
|
ImageCount int `gorm:"default:0" json:"image_count" comment:"图片数量"`
|
||||||
CozeTag string `gorm:"type:varchar(500)" json:"coze_tag" comment:"Coze生成的标签"`
|
CozeTag string `gorm:"type:varchar(500)" json:"coze_tag" comment:"Coze生成的标签"`
|
||||||
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
||||||
UpdatedAt time.Time `gorm:"index:idx_updated_at" json:"updated_at" comment:"更新时间"`
|
UpdatedAt time.Time `gorm:"index:idx_updated_at" json:"updated_at" comment:"更新时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy 文案表别名,兼容旧代码
|
// Copy 文案表别名,兼容旧代码
|
||||||
@@ -108,83 +110,85 @@ type Copy = Article
|
|||||||
|
|
||||||
// PublishRecord 发布记录表(对应ai_article_published_records)
|
// PublishRecord 发布记录表(对应ai_article_published_records)
|
||||||
type PublishRecord struct {
|
type PublishRecord struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
ArticleID *int `gorm:"index:idx_article_id" json:"article_id" comment:"文章ID"`
|
ArticleID *int `gorm:"index:idx_article_id" json:"article_id" comment:"文章ID"`
|
||||||
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
ProductID int `gorm:"not null;default:0;index:idx_product_id" json:"product_id" comment:"关联产品ID"`
|
ProductID int `gorm:"not null;default:0;index:idx_product_id" json:"product_id" comment:"关联产品ID"`
|
||||||
Topic string `gorm:"type:varchar(255);not null;default:''" json:"topic" comment:"topic主题"`
|
Topic string `gorm:"type:varchar(255);not null;default:''" json:"topic" comment:"topic主题"`
|
||||||
Title string `gorm:"type:varchar(200);not null;default:''" json:"title" comment:"标题"`
|
Title string `gorm:"type:varchar(200);not null;default:''" json:"title" comment:"标题"`
|
||||||
CreatedUserID int `gorm:"not null;default:0;index:idx_created_user_id" json:"created_user_id" comment:"创建用户ID"`
|
CreatedUserID int `gorm:"not null;default:0;index:idx_created_user_id" json:"created_user_id" comment:"创建用户ID"`
|
||||||
ReviewUserID *int `json:"review_user_id" comment:"审核用户ID"`
|
ReviewUserID *int `json:"review_user_id" comment:"审核用户ID"`
|
||||||
PublishUserID *int `json:"publish_user_id" comment:"发布用户ID"`
|
PublishUserID *int `json:"publish_user_id" comment:"发布用户ID"`
|
||||||
Status string `gorm:"type:enum('topic','cover_image','generate','generate_failed','draft','pending_review','approved','rejected','published_review','published','failed');default:'draft';index:idx_status" json:"status" comment:"状态"`
|
Status string `gorm:"type:enum('topic','cover_image','generate','generate_failed','draft','pending_review','assign_authors','approved','rejected','published_review','published','failed');default:'draft';index:idx_status" json:"status" comment:"状态"`
|
||||||
Channel int `gorm:"type:tinyint(1);not null;default:1" json:"channel" comment:"渠道:1=baidu|2=toutiao|3=weixin"`
|
Channel int `gorm:"type:tinyint(1);not null;default:1" json:"channel" comment:"渠道:1=baidu|2=toutiao|3=weixin"`
|
||||||
ReviewComment string `gorm:"type:text" json:"review_comment" comment:"审核评论"`
|
ReviewComment string `gorm:"type:text" json:"review_comment" comment:"审核评论"`
|
||||||
PublishTime *time.Time `json:"publish_time" comment:"发布时间"`
|
PublishTime *time.Time `json:"publish_time" comment:"发布时间"`
|
||||||
PublishLink string `gorm:"type:varchar(128);not null;default:''" json:"publish_link" comment:"发布访问链接"`
|
PublishLink string `gorm:"type:varchar(128);not null;default:''" json:"publish_link" comment:"发布访问链接"`
|
||||||
WordCount int `gorm:"default:0" json:"word_count" comment:"字数统计"`
|
WordCount int `gorm:"default:0" json:"word_count" comment:"字数统计"`
|
||||||
ImageCount int `gorm:"default:0" json:"image_count" comment:"图片数量"`
|
ImageCount int `gorm:"default:0" json:"image_count" comment:"图片数量"`
|
||||||
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
||||||
UpdatedAt time.Time `gorm:"index:idx_updated_at" json:"updated_at" comment:"更新时间"`
|
UpdatedAt time.Time `gorm:"index:idx_updated_at" json:"updated_at" comment:"更新时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// XHSAccount 小红书账号表(保持兼容)
|
// XHSAccount 小红书账号表(保持兼容)
|
||||||
type XHSAccount struct {
|
type XHSAccount struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
EmployeeID int `gorm:"not null;default:0;uniqueIndex:uk_employee_id" json:"employee_id"`
|
EmployeeID int `gorm:"not null;default:0;uniqueIndex:uk_employee_id" json:"employee_id"`
|
||||||
Employee User `gorm:"foreignKey:EmployeeID" json:"employee,omitempty"`
|
Employee User `gorm:"foreignKey:EmployeeID" json:"employee,omitempty"`
|
||||||
XHSUserID string `gorm:"type:varchar(100);not null;default:'';index:idx_xhs_user_id" json:"xhs_user_id"`
|
XHSUserID string `gorm:"type:varchar(100);not null;default:'';index:idx_xhs_user_id" json:"xhs_user_id"`
|
||||||
XHSNickname string `gorm:"type:varchar(100);not null;default:''" json:"xhs_nickname"`
|
XHSNickname string `gorm:"type:varchar(100);not null;default:''" json:"xhs_nickname"`
|
||||||
XHSPhone string `gorm:"type:varchar(20);not null;default:''" json:"xhs_phone"`
|
XHSPhone string `gorm:"type:varchar(20);not null;default:''" json:"xhs_phone"`
|
||||||
XHSAvatar string `gorm:"type:varchar(500);not null;default:''" json:"xhs_avatar"`
|
XHSAvatar string `gorm:"type:varchar(500);not null;default:''" json:"xhs_avatar"`
|
||||||
FansCount int `gorm:"not null;default:0" json:"fans_count"`
|
FansCount int `gorm:"not null;default:0" json:"fans_count"`
|
||||||
NotesCount int `gorm:"not null;default:0" json:"notes_count"`
|
NotesCount int `gorm:"not null;default:0" json:"notes_count"`
|
||||||
Cookies string `gorm:"type:text" json:"cookies"`
|
Cookies string `gorm:"type:text" json:"cookies"`
|
||||||
AccessToken string `gorm:"type:varchar(500);not null;default:''" json:"access_token"`
|
AccessToken string `gorm:"type:varchar(500);not null;default:''" json:"access_token"`
|
||||||
RefreshToken string `gorm:"type:varchar(500);not null;default:''" json:"refresh_token"`
|
RefreshToken string `gorm:"type:varchar(500);not null;default:''" json:"refresh_token"`
|
||||||
TokenExpireAt *time.Time `json:"token_expire_at"`
|
TokenExpireAt *time.Time `json:"token_expire_at"`
|
||||||
Status string `gorm:"type:enum('active','expired','banned');default:'active';index:idx_status" json:"status"`
|
Status string `gorm:"type:enum('active','expired','banned');default:'active';index:idx_status" json:"status"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PromptWorkflow 提示词工作流表
|
// PromptWorkflow 提示词工作流表
|
||||||
type PromptWorkflow struct {
|
type PromptWorkflow struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
PromptWorkflowName string `gorm:"type:varchar(100);not null;default:''" json:"prompt_workflow_name" comment:"提示词工作流名称"`
|
PromptWorkflowName string `gorm:"type:varchar(100);not null;default:''" json:"prompt_workflow_name" comment:"提示词工作流名称"`
|
||||||
AuthToken string `gorm:"type:varchar(100);not null;default:''" json:"auth_token" comment:"认证Token"`
|
AuthToken string `gorm:"type:varchar(100);not null;default:''" json:"auth_token" comment:"认证Token"`
|
||||||
WorkflowID string `gorm:"type:varchar(100);not null;default:'';index:idx_workflow_id" json:"workflow_id" comment:"工作流ID"`
|
WorkflowID string `gorm:"type:varchar(100);not null;default:'';index:idx_workflow_id" json:"workflow_id" comment:"工作流ID"`
|
||||||
Content string `gorm:"type:text" json:"content" comment:"提示词内容"`
|
Content string `gorm:"type:text" json:"content" comment:"提示词内容"`
|
||||||
UsageCount int `gorm:"not null;default:0" json:"usage_count" comment:"使用次数统计"`
|
UsageCount int `gorm:"not null;default:0" json:"usage_count" comment:"使用次数统计"`
|
||||||
CreatedUserID int `gorm:"not null;default:0" json:"created_user_id" comment:"创建用户ID"`
|
CreatedUserID int `gorm:"not null;default:0" json:"created_user_id" comment:"创建用户ID"`
|
||||||
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
||||||
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProductImage 产品图片库表
|
// ProductImage 产品图片库表
|
||||||
type ProductImage struct {
|
type ProductImage struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
ProductID int `gorm:"not null;default:0;index:idx_product_id" json:"product_id" comment:"关联产品ID"`
|
ProductID int `gorm:"not null;default:0;index:idx_product_id" json:"product_id" comment:"关联产品ID"`
|
||||||
ImageID int `gorm:"not null;default:0" json:"image_id" comment:"图片ID"`
|
ProductName string `gorm:"type:varchar(256);not null;default:''" json:"product_name" comment:"产品名称"`
|
||||||
ImageName string `gorm:"type:varchar(255);not null;default:''" json:"image_name" comment:"图片名称"`
|
ImageID int `gorm:"not null;default:0" json:"image_id" comment:"图片ID"`
|
||||||
ImageURL string `gorm:"type:varchar(500);not null;default:''" json:"image_url" comment:"图片URL"`
|
ImageName string `gorm:"type:varchar(255);not null;default:''" json:"image_name" comment:"图片名称"`
|
||||||
ThumbnailURL string `gorm:"type:varchar(500);not null;default:''" json:"thumbnail_url" comment:"缩略图URL"`
|
ImageURL string `gorm:"type:varchar(500);not null;default:''" json:"image_url" comment:"图片URL"`
|
||||||
TypeName string `gorm:"type:varchar(50);not null;default:''" json:"type_name" comment:"图片类型"`
|
ThumbnailURL string `gorm:"type:varchar(500);not null;default:''" json:"thumbnail_url" comment:"缩略图URL"`
|
||||||
Description string `gorm:"type:varchar(500);not null;default:''" json:"description" comment:"图片描述"`
|
TypeName string `gorm:"type:varchar(50);not null;default:''" json:"type_name" comment:"图片类型"`
|
||||||
FileSize *int64 `json:"file_size" comment:"文件大小"`
|
Description string `gorm:"type:varchar(500);not null;default:''" json:"description" comment:"图片描述"`
|
||||||
Width *int `json:"width" comment:"图片宽度"`
|
FileSize *int64 `json:"file_size" comment:"文件大小"`
|
||||||
Height *int `json:"height" comment:"图片高度"`
|
Width *int `json:"width" comment:"图片宽度"`
|
||||||
UploadUserID int `gorm:"not null;default:0" json:"upload_user_id" comment:"上传用户ID"`
|
Height *int `json:"height" comment:"图片高度"`
|
||||||
Status string `gorm:"type:enum('active','deleted');default:'active';index:idx_status" json:"status" comment:"状态"`
|
UploadUserID int `gorm:"not null;default:0" json:"upload_user_id" comment:"上传用户ID"`
|
||||||
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"上传时间"`
|
Status string `gorm:"type:enum('active','deleted');default:'active';index:idx_status" json:"status" comment:"状态"`
|
||||||
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"上传时间"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArticleImage 文章图片表
|
// ArticleImage 文章图片表
|
||||||
type ArticleImage struct {
|
type ArticleImage struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
|
EnterpriseID int `gorm:"not null;default:0" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
ArticleID int `gorm:"not null;default:0;index:idx_article_id" json:"article_id" comment:"文章ID"`
|
ArticleID int `gorm:"not null;default:0;index:idx_article_id" json:"article_id" comment:"文章ID"`
|
||||||
ImageID int `gorm:"not null;default:0;index:idx_image_id" json:"image_id" comment:"图片ID"`
|
ImageID int `gorm:"not null;default:0;index:idx_image_id" json:"image_id" comment:"图片ID"`
|
||||||
ImageURL string `gorm:"type:varchar(500);not null;default:''" json:"image_url" comment:"图片URL"`
|
ImageURL string `gorm:"type:varchar(500);not null;default:''" json:"image_url" comment:"图片URL"`
|
||||||
@@ -202,23 +206,24 @@ type ArticleImage struct {
|
|||||||
|
|
||||||
// ArticleTag 文章标签表
|
// ArticleTag 文章标签表
|
||||||
type ArticleTag struct {
|
type ArticleTag struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
ArticleID int `gorm:"not null;default:0;uniqueIndex:uk_article_tag" json:"article_id" comment:"文章ID"`
|
EnterpriseID int `gorm:"not null;default:0" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
CozeTag string `gorm:"type:varchar(500)" json:"coze_tag" comment:"Coze生成的标签"`
|
ArticleID int `gorm:"not null;default:0;uniqueIndex:uk_article_tag" json:"article_id" comment:"文章ID"`
|
||||||
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
CozeTag string `gorm:"type:varchar(500)" json:"coze_tag" comment:"Coze生成的标签"`
|
||||||
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataStatistics 数据统计表
|
// DataStatistics 数据统计表
|
||||||
type DataStatistics struct {
|
type DataStatistics struct {
|
||||||
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
EnterpriseID int `gorm:"not null;default:0;index:idx_enterprise_id" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
ProductID int `gorm:"not null;default:0;index:idx_product_id" json:"product_id" comment:"关联产品ID"`
|
ProductID int `gorm:"not null;default:0;index:idx_product_id" json:"product_id" comment:"关联产品ID"`
|
||||||
CumulativeReleasesNum int `gorm:"type:int(10) unsigned;not null;default:0" json:"cumulative_releases_num" comment:"累计发布"`
|
CumulativeReleasesNum int `gorm:"type:int(10) unsigned;not null;default:0" json:"cumulative_releases_num" comment:"累计发布"`
|
||||||
PublishedTodayNum int `gorm:"type:int(10) unsigned;not null;default:0" json:"published_today_num" comment:"今日发布"`
|
PublishedTodayNum int `gorm:"type:int(10) unsigned;not null;default:0" json:"published_today_num" comment:"今日发布"`
|
||||||
PublishedWeekNum int `gorm:"type:int(10) unsigned;not null;default:0" json:"published_week_num" comment:"本周发布"`
|
PublishedWeekNum int `gorm:"type:int(10) unsigned;not null;default:0" json:"published_week_num" comment:"本周发布"`
|
||||||
ParticipatingEmployees int `gorm:"type:int(10) unsigned;not null;default:0" json:"participating_employees_num" comment:"参与员工"`
|
ParticipatingEmployees int `gorm:"type:int(10) unsigned;not null;default:0" json:"participating_employees_num" comment:"参与员工"`
|
||||||
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
||||||
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log 操作日志表(对应ai_logs)
|
// Log 操作日志表(对应ai_logs)
|
||||||
@@ -238,6 +243,31 @@ type Log struct {
|
|||||||
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Author 作者表(对应ai_authors)
|
||||||
|
type Author struct {
|
||||||
|
ID int `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||||
|
EnterpriseID int `gorm:"not null;default:0" json:"enterprise_id" comment:"所属企业ID"`
|
||||||
|
CreatedUserID int `gorm:"not null;default:0" json:"created_user_id" comment:"创建用户ID"`
|
||||||
|
Phone string `gorm:"type:varchar(20)" json:"phone" comment:"手机号"`
|
||||||
|
AuthorName string `gorm:"type:varchar(100);not null;default:''" json:"author_name" comment:"作者名称"`
|
||||||
|
AppID string `gorm:"type:varchar(127);not null;default:''" json:"app_id" comment:"应用ID"`
|
||||||
|
AppToken string `gorm:"type:varchar(127);not null;default:''" json:"app_token" comment:"应用Token"`
|
||||||
|
DepartmentID int `gorm:"not null;default:0" json:"department_id" comment:"部门ID"`
|
||||||
|
DepartmentName string `gorm:"type:varchar(255);not null;default:''" json:"department_name" comment:"部门名称"`
|
||||||
|
Department string `gorm:"type:varchar(50);not null;default:''" json:"department" comment:"部门"`
|
||||||
|
Title string `gorm:"type:varchar(50)" json:"title" comment:"职称"`
|
||||||
|
Hospital string `gorm:"type:varchar(100)" json:"hospital" comment:"医院"`
|
||||||
|
Specialty string `gorm:"type:text" json:"specialty" comment:"专业"`
|
||||||
|
ToutiaoCookie string `gorm:"type:text" json:"toutiao_cookie" comment:"头条Cookie"`
|
||||||
|
ToutiaoImagesCookie string `gorm:"type:text" json:"toutiao_images_cookie" comment:"头条图片Cookie"`
|
||||||
|
Introduction string `gorm:"type:text" json:"introduction" comment:"介绍"`
|
||||||
|
AvatarURL string `gorm:"type:varchar(255)" json:"avatar_url" comment:"头像URL"`
|
||||||
|
Status string `gorm:"type:enum('active','inactive');default:'active';index:idx_status" json:"status" comment:"状态"`
|
||||||
|
Channel int `gorm:"type:tinyint(1);not null;default:1" json:"channel" comment:"渠道:1=baidu|2=toutiao|3=weixin"`
|
||||||
|
CreatedAt time.Time `gorm:"index:idx_created_at" json:"created_at" comment:"创建时间"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at" comment:"更新时间"`
|
||||||
|
}
|
||||||
|
|
||||||
// TableName 指定表名(带ai_前缀)
|
// TableName 指定表名(带ai_前缀)
|
||||||
func (Enterprise) TableName() string {
|
func (Enterprise) TableName() string {
|
||||||
return "ai_enterprises"
|
return "ai_enterprises"
|
||||||
@@ -286,3 +316,7 @@ func (DataStatistics) TableName() string {
|
|||||||
func (Log) TableName() string {
|
func (Log) TableName() string {
|
||||||
return "ai_logs"
|
return "ai_logs"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Author) TableName() string {
|
||||||
|
return "ai_authors"
|
||||||
|
}
|
||||||
|
|||||||
@@ -66,6 +66,9 @@ func SetupRouter(r *gin.Engine) {
|
|||||||
|
|
||||||
// 10.9 检查小红书绑定与Cookie状态
|
// 10.9 检查小红书绑定与Cookie状态
|
||||||
employee.GET("/xhs/status", employeeCtrl.CheckXHSStatus)
|
employee.GET("/xhs/status", employeeCtrl.CheckXHSStatus)
|
||||||
|
|
||||||
|
// 10.10 更新文案状态(通过/拒绝)
|
||||||
|
employee.POST("/article/:id/status", employeeCtrl.UpdateArticleStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthService struct{}
|
type AuthService struct{}
|
||||||
@@ -141,33 +143,95 @@ func (s *AuthService) WechatLogin(code string, phone string, phoneCode string) (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 根据OpenID查找或创建员工
|
// 2. 根据手机号查找用户(手机号必填)
|
||||||
|
if phone == "" {
|
||||||
|
return "", nil, errors.New("请提供手机号")
|
||||||
|
}
|
||||||
|
|
||||||
var employee models.User
|
var employee models.User
|
||||||
|
// 通过手机号查找员工
|
||||||
// 优先通过OpenID查找(注意:使用IS NOT NULL过滤空值)
|
result := database.DB.Where("phone = ? AND status = ?", phone, "active").First(&employee)
|
||||||
result := database.DB.Where("wechat_openid = ? AND wechat_openid IS NOT NULL", wxResp.OpenID).First(&employee)
|
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
// OpenID不存在,需要绑定OpenID
|
// 手机号不存在,不允许登录
|
||||||
if phone == "" {
|
return "", nil, errors.New("手机号不存在,请联系管理员添加")
|
||||||
return "", nil, errors.New("首次登录请提供手机号")
|
}
|
||||||
|
|
||||||
|
// 3. 检查微信绑定信息
|
||||||
|
// 如果该用户已绑定微信信息,必须与当前登录的微信信息一致(单设备登录)
|
||||||
|
if employee.WechatOpenID != nil && *employee.WechatOpenID != "" {
|
||||||
|
// 已绑定微信,检查是否一致
|
||||||
|
if *employee.WechatOpenID != wxResp.OpenID {
|
||||||
|
return "", nil, errors.New("该账号已在其他设备登录,请使用原设备登录或联系管理员")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过手机号查找员工
|
// 如果有UnionID,也需要检查一致性
|
||||||
result = database.DB.Where("phone = ? AND status = ?", phone, "active").First(&employee)
|
if employee.WechatUnionID != nil && *employee.WechatUnionID != "" && wxResp.UnionID != "" {
|
||||||
if result.Error != nil {
|
if *employee.WechatUnionID != wxResp.UnionID {
|
||||||
return "", nil, errors.New("员工不存在,请联系管理员添加")
|
return "", nil, errors.New("微信账号信息不匹配,请使用原设备登录")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绑定OpenID和UnionID(使用指针)
|
log.Printf("[微信登录] 用户 %s (ID:%d) 微信验证通过", employee.Phone, employee.ID)
|
||||||
|
} else {
|
||||||
|
// 微信信息为空,说明是新用户首次登录,保存微信信息
|
||||||
|
log.Printf("[微信登录] 新用户首次登录,绑定微信信息: OpenID=%s, UnionID=%s", wxResp.OpenID, wxResp.UnionID)
|
||||||
|
|
||||||
employee.WechatOpenID = &wxResp.OpenID
|
employee.WechatOpenID = &wxResp.OpenID
|
||||||
if wxResp.UnionID != "" {
|
if wxResp.UnionID != "" {
|
||||||
employee.WechatUnionID = &wxResp.UnionID
|
employee.WechatUnionID = &wxResp.UnionID
|
||||||
}
|
}
|
||||||
database.DB.Save(&employee)
|
|
||||||
|
// 使用事务保存微信绑定信息并创建作者记录
|
||||||
|
err := database.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// 1. 保存微信绑定信息
|
||||||
|
if err := tx.Save(&employee).Error; err != nil {
|
||||||
|
return fmt.Errorf("保存微信绑定信息失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 检查是否已存在作者记录(通过手机号和企业ID)
|
||||||
|
var existingAuthor models.Author
|
||||||
|
result := tx.Where("phone = ? AND enterprise_id = ?", employee.Phone, employee.EnterpriseID).First(&existingAuthor)
|
||||||
|
|
||||||
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||||
|
// 作者记录不存在,创建新记录
|
||||||
|
author := models.Author{
|
||||||
|
EnterpriseID: employee.EnterpriseID,
|
||||||
|
CreatedUserID: employee.ID,
|
||||||
|
Phone: employee.Phone,
|
||||||
|
AuthorName: employee.RealName,
|
||||||
|
Department: employee.Department,
|
||||||
|
Status: "active",
|
||||||
|
Channel: 3, // 3=weixin (微信小程序)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果真实姓名为空,使用用户名
|
||||||
|
if author.AuthorName == "" {
|
||||||
|
author.AuthorName = employee.Username
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Create(&author).Error; err != nil {
|
||||||
|
return fmt.Errorf("创建作者记录失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[微信登录] 创建作者记录成功: ID=%d, Name=%s", author.ID, author.AuthorName)
|
||||||
|
} else if result.Error != nil {
|
||||||
|
// 其他数据库错误
|
||||||
|
return fmt.Errorf("检查作者记录失败: %v", result.Error)
|
||||||
|
} else {
|
||||||
|
log.Printf("[微信登录] 作者记录已存在: ID=%d", existingAuthor.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[微信登录] 用户 %s (ID:%d) 微信绑定成功", employee.Phone, employee.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 生成JWT token
|
// 4. 生成JWT token
|
||||||
token, err := utils.GenerateToken(employee.ID)
|
token, err := utils.GenerateToken(employee.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, fmt.Errorf("生成token失败: %v", err)
|
return "", nil, fmt.Errorf("生成token失败: %v", err)
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ func (s *EmployeeService) SendXHSCode(phone string) error {
|
|||||||
|
|
||||||
// 执行命令
|
// 执行命令
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
|
|
||||||
// 打印Python脚本的日志输出(stderr)
|
// 打印Python脚本的日志输出(stderr)
|
||||||
if stderr.Len() > 0 {
|
if stderr.Len() > 0 {
|
||||||
log.Printf("[Python日志-发送验证码] %s", stderr.String())
|
log.Printf("[Python日志-发送验证码] %s", stderr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("执行Python脚本失败: %w, stderr: %s", err, stderr.String())
|
return fmt.Errorf("执行Python脚本失败: %w, stderr: %s", err, stderr.String())
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ func (s *EmployeeService) GetProfile(employeeID int) (*models.User, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果已绑定小红书且有Cookie,验证Cookie是否有效
|
// 如果已绑定小红书且有Cookie,验证Cookie是否有效
|
||||||
if employee.IsBoundXHS == 1 && employee.XHSCookie != "" {
|
if employee.IsBoundXHS == 1 && employee.XHSCookie != "" {
|
||||||
// 检查绑定时间,刚绑定的30秒内不验证(避免与绑定操作冲突)
|
// 检查绑定时间,刚绑定的30秒内不验证(避免与绑定操作冲突)
|
||||||
@@ -96,7 +96,7 @@ func (s *EmployeeService) GetProfile(employeeID int) (*models.User, error) {
|
|||||||
log.Printf("GetProfile - 用户%d有Cookie,长度: %d(已跳过自动验证)", employeeID, len(employee.XHSCookie))
|
log.Printf("GetProfile - 用户%d有Cookie,长度: %d(已跳过自动验证)", employeeID, len(employee.XHSCookie))
|
||||||
// go s.VerifyCookieAndClear(employeeID)
|
// go s.VerifyCookieAndClear(employeeID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &employee, nil
|
return &employee, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ func (s *EmployeeService) BindXHS(employeeID int, xhsPhone, code string) (string
|
|||||||
} else {
|
} else {
|
||||||
log.Printf("绑定小红书 - 用户%d - 警告: cookiesData为nil", employeeID)
|
log.Printf("绑定小红书 - 用户%d - 警告: cookiesData为nil", employeeID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cookiesJSON == "" {
|
if cookiesJSON == "" {
|
||||||
log.Printf("绑定小红书 - 用户%d - 错误: 未能获取到Cookie数据", employeeID)
|
log.Printf("绑定小红书 - 用户%d - 错误: 未能获取到Cookie数据", employeeID)
|
||||||
return "", errors.New("登录成功但未能获取到Cookie数据,请重试")
|
return "", errors.New("登录成功但未能获取到Cookie数据,请重试")
|
||||||
@@ -195,7 +195,7 @@ func (s *EmployeeService) BindXHS(employeeID int, xhsPhone, code string) (string
|
|||||||
log.Printf("绑定小红书 - 用户%d - 数据库更新失败: %v", employeeID, err)
|
log.Printf("绑定小红书 - 用户%d - 数据库更新失败: %v", employeeID, err)
|
||||||
return "", fmt.Errorf("更新员工绑定状态失败: %w", err)
|
return "", fmt.Errorf("更新员工绑定状态失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("绑定小红书 - 用户%d - 数据库更新成功", employeeID)
|
log.Printf("绑定小红书 - 用户%d - 数据库更新成功", employeeID)
|
||||||
|
|
||||||
// 提交事务
|
// 提交事务
|
||||||
@@ -203,7 +203,7 @@ func (s *EmployeeService) BindXHS(employeeID int, xhsPhone, code string) (string
|
|||||||
log.Printf("绑定小红书 - 用户%d - 事务提交失败: %v", employeeID, err)
|
log.Printf("绑定小红书 - 用户%d - 事务提交失败: %v", employeeID, err)
|
||||||
return "", fmt.Errorf("提交事务失败: %w", err)
|
return "", fmt.Errorf("提交事务失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("绑定小红书 - 用户%d - 绑定成功 - 账号: %s", employeeID, xhsNickname)
|
log.Printf("绑定小红书 - 用户%d - 绑定成功 - 账号: %s", employeeID, xhsNickname)
|
||||||
return xhsNickname, nil
|
return xhsNickname, nil
|
||||||
}
|
}
|
||||||
@@ -381,7 +381,7 @@ func (s *EmployeeService) VerifyCookieAndClear(employeeID int) error {
|
|||||||
if employee.IsBoundXHS == 0 || employee.XHSCookie == "" {
|
if employee.IsBoundXHS == 0 || employee.XHSCookie == "" {
|
||||||
return nil // 没有绑定或已无Cookie,直接返回
|
return nil // 没有绑定或已无Cookie,直接返回
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查绑定时间,刚绑定的30秒内不验证(避免与绑定操作冲突)
|
// 检查绑定时间,刚绑定的30秒内不验证(避免与绑定操作冲突)
|
||||||
if employee.BoundAt != nil {
|
if employee.BoundAt != nil {
|
||||||
timeSinceBound := time.Since(*employee.BoundAt)
|
timeSinceBound := time.Since(*employee.BoundAt)
|
||||||
@@ -492,20 +492,37 @@ func (s *EmployeeService) clearXHSCookie(employeeID int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAvailableCopies 获取可领取的文案列表
|
// GetAvailableCopies 获取可领取的文案列表(根据作者ID、产品ID和状态筛选)
|
||||||
func (s *EmployeeService) GetAvailableCopies(employeeID int, productID int) (map[string]interface{}, error) {
|
func (s *EmployeeService) GetAvailableCopies(employeeID int, productID int) (map[string]interface{}, error) {
|
||||||
|
// 获取当前用户信息,查找对应的作者ID
|
||||||
|
var employee models.User
|
||||||
|
if err := database.DB.First(&employee, employeeID).Error; err != nil {
|
||||||
|
return nil, fmt.Errorf("获取用户信息失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找对应的作者记录
|
||||||
|
var author models.Author
|
||||||
|
if err := database.DB.Where("phone = ? AND enterprise_id = ?", employee.Phone, employee.EnterpriseID).First(&author).Error; err != nil {
|
||||||
|
return nil, fmt.Errorf("未找到对应的作者记录: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// 获取产品信息
|
// 获取产品信息
|
||||||
var product models.Product
|
var product models.Product
|
||||||
if err := database.DB.First(&product, productID).Error; err != nil {
|
if err := database.DB.First(&product, productID).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取该产品下所有可用文案(注意:新数据库中status有更多状态)
|
// 根据产品ID、作者ID和状态筛选文案
|
||||||
|
// status = 'assign_authors' 表示已分配作者的文案
|
||||||
var copies []models.Article
|
var copies []models.Article
|
||||||
if err := database.DB.Where("product_id = ? AND status IN ?", productID, []string{"draft", "approved"}).Order("created_at DESC").Find(&copies).Error; err != nil {
|
query := database.DB.Where("product_id = ? AND author_id = ? AND status = ?", productID, author.ID, "assign_authors")
|
||||||
return nil, err
|
|
||||||
|
if err := query.Order("created_at DESC").Find(&copies).Error; err != nil {
|
||||||
|
return nil, fmt.Errorf("查询文案列表失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("[获取文案列表] 用户ID=%d, 作者ID=%d, 产品ID=%d, 筛选到 %d 条文案", employeeID, author.ID, productID, len(copies))
|
||||||
|
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"product": map[string]interface{}{
|
"product": map[string]interface{}{
|
||||||
"id": product.ID,
|
"id": product.ID,
|
||||||
@@ -513,14 +530,106 @@ func (s *EmployeeService) GetAvailableCopies(employeeID int, productID int) (map
|
|||||||
"image": product.ImageURL,
|
"image": product.ImageURL,
|
||||||
},
|
},
|
||||||
"copies": copies,
|
"copies": copies,
|
||||||
|
"author": map[string]interface{}{
|
||||||
|
"id": author.ID,
|
||||||
|
"name": author.AuthorName,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateArticleStatus 更新文案状态(通过/拒绝)
|
||||||
|
func (s *EmployeeService) UpdateArticleStatus(employeeID int, articleID int, status string) error {
|
||||||
|
// 获取当前用户信息
|
||||||
|
var employee models.User
|
||||||
|
if err := database.DB.First(&employee, employeeID).Error; err != nil {
|
||||||
|
return fmt.Errorf("获取用户信息失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找对应的作者记录
|
||||||
|
var author models.Author
|
||||||
|
if err := database.DB.Where("phone = ? AND enterprise_id = ?", employee.Phone, employee.EnterpriseID).First(&author).Error; err != nil {
|
||||||
|
return fmt.Errorf("未找到对应的作者记录: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文案信息
|
||||||
|
var article models.Article
|
||||||
|
if err := database.DB.First(&article, articleID).Error; err != nil {
|
||||||
|
return fmt.Errorf("获取文案信息失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证文案是否属于当前作者且状态为assign_authors
|
||||||
|
if article.AuthorID == nil || *article.AuthorID != author.ID {
|
||||||
|
return fmt.Errorf("无权操作此文案")
|
||||||
|
}
|
||||||
|
|
||||||
|
if article.Status != "assign_authors" {
|
||||||
|
return fmt.Errorf("文案当前状态为%s,无法操作", article.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启事务
|
||||||
|
tx := database.DB.Begin()
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
// 更新文案状态
|
||||||
|
err := tx.Model(&article).Updates(map[string]interface{}{
|
||||||
|
"status": status,
|
||||||
|
"review_user_id": employeeID,
|
||||||
|
}).Error
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("更新状态失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建操作记录到 ai_article_published_records
|
||||||
|
actionType := "通过"
|
||||||
|
if status == "rejected" {
|
||||||
|
actionType = "拒绝"
|
||||||
|
}
|
||||||
|
|
||||||
|
record := models.PublishRecord{
|
||||||
|
ArticleID: &article.ID,
|
||||||
|
EnterpriseID: employee.EnterpriseID,
|
||||||
|
ProductID: article.ProductID,
|
||||||
|
Topic: article.Topic,
|
||||||
|
Title: article.Title,
|
||||||
|
CreatedUserID: article.CreatedUserID,
|
||||||
|
ReviewUserID: &employeeID,
|
||||||
|
Status: status,
|
||||||
|
PublishTime: &now,
|
||||||
|
WordCount: article.WordCount,
|
||||||
|
ImageCount: article.ImageCount,
|
||||||
|
Channel: article.Channel,
|
||||||
|
ReviewComment: fmt.Sprintf("作者%s于%s", actionType, now.Format("2006-01-02 15:04:05")),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Create(&record).Error; err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("创建操作记录失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交事务
|
||||||
|
if err := tx.Commit().Error; err != nil {
|
||||||
|
return fmt.Errorf("提交事务失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[更新文案状态] 用户ID=%d, 作者ID=%d, 文案ID=%d, 状态: assign_authors => %s, 记录ID=%d", employeeID, author.ID, articleID, status, record.ID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ClaimCopy 领取文案(新版本:直接返回文案信息,不再创建领取记录)
|
// ClaimCopy 领取文案(新版本:直接返回文案信息,不再创建领取记录)
|
||||||
func (s *EmployeeService) ClaimCopy(employeeID int, copyID int, productID int) (map[string]interface{}, error) {
|
func (s *EmployeeService) ClaimCopy(employeeID int, copyID int, productID int) (map[string]interface{}, error) {
|
||||||
// 检查文案是否存在且可用(注意:新数据库中status有更多状态)
|
// 检查文案是否存在且可用(注意:新数据库中status有更多状态)
|
||||||
|
// assign_authors: 已分配给作者,可以直接发布
|
||||||
|
// draft: 草稿状态
|
||||||
|
// approved: 已审核通过
|
||||||
var copy models.Article
|
var copy models.Article
|
||||||
if err := database.DB.Where("id = ? AND status IN ?", copyID, []string{"draft", "approved"}).First(©).Error; err != nil {
|
if err := database.DB.Where("id = ? AND status IN ?", copyID, []string{"draft", "approved", "assign_authors"}).First(©).Error; err != nil {
|
||||||
return nil, errors.New("文案不存在或不可用")
|
return nil, errors.New("文案不存在或不可用")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,7 +651,7 @@ func (s *EmployeeService) ClaimCopy(employeeID int, copyID int, productID int) (
|
|||||||
func (s *EmployeeService) ClaimRandomCopy(employeeID int, productID int) (map[string]interface{}, error) {
|
func (s *EmployeeService) ClaimRandomCopy(employeeID int, productID int) (map[string]interface{}, error) {
|
||||||
// 查询未领取的可用文案(注意:新数据库中status有更多状态)
|
// 查询未领取的可用文案(注意:新数据库中status有更多状态)
|
||||||
var copy models.Article
|
var copy models.Article
|
||||||
query := database.DB.Where("product_id = ? AND status IN ?", productID, []string{"draft", "approved"})
|
query := database.DB.Where("product_id = ? AND status IN ?", productID, []string{"draft", "approved", "assign_authors"})
|
||||||
|
|
||||||
if err := query.Order("RAND()").First(©).Error; err != nil {
|
if err := query.Order("RAND()").First(©).Error; err != nil {
|
||||||
return nil, errors.New("暂无可领取的文案")
|
return nil, errors.New("暂无可领取的文案")
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ interface EnvConfig {
|
|||||||
const API_CONFIG: Record<EnvType, EnvConfig> = {
|
const API_CONFIG: Record<EnvType, EnvConfig> = {
|
||||||
// 开发环境 - 本地开发
|
// 开发环境 - 本地开发
|
||||||
dev: {
|
dev: {
|
||||||
baseURL: 'http://localhost:8080', // 本地Go服务
|
baseURL: 'http://192.168.17.127:8080', // 本地Go服务
|
||||||
pythonURL: 'http://localhost:8000', // 本地Python服务
|
pythonURL: 'http://192.168.17.127:8000', // 本地Python服务
|
||||||
timeout: 90000
|
timeout: 90000
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ Page({
|
|||||||
currentCopy: null as any, // 当前显示的文案
|
currentCopy: null as any, // 当前显示的文案
|
||||||
loading: false,
|
loading: false,
|
||||||
claiming: false, // 领取中
|
claiming: false, // 领取中
|
||||||
publishing: false // 发布中
|
publishing: false, // 发布中
|
||||||
|
rejecting: false // 拒绝中
|
||||||
},
|
},
|
||||||
|
|
||||||
onLoad(options: any) {
|
onLoad(options: any) {
|
||||||
@@ -150,7 +151,7 @@ Page({
|
|||||||
|
|
||||||
// 换一个文案
|
// 换一个文案
|
||||||
changeArticle() {
|
changeArticle() {
|
||||||
if (this.data.claiming || this.data.publishing) return;
|
if (this.data.claiming || this.data.publishing || this.data.rejecting) return;
|
||||||
|
|
||||||
const { allCopies, currentIndex } = this.data;
|
const { allCopies, currentIndex } = this.data;
|
||||||
|
|
||||||
@@ -162,19 +163,25 @@ Page({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换到下一个文案
|
// 显示加载动画
|
||||||
const nextIndex = (currentIndex + 1) % allCopies.length;
|
wx.showLoading({
|
||||||
|
title: '加载中...',
|
||||||
this.setData({
|
mask: true
|
||||||
currentIndex: nextIndex,
|
|
||||||
currentCopy: allCopies[nextIndex]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
wx.showToast({
|
// 模拟加载效果,让切换更平滑
|
||||||
title: `${nextIndex + 1}/${allCopies.length}`,
|
setTimeout(() => {
|
||||||
icon: 'none',
|
// 切换到下一个文案
|
||||||
duration: 1000
|
const nextIndex = (currentIndex + 1) % allCopies.length;
|
||||||
});
|
|
||||||
|
this.setData({
|
||||||
|
currentIndex: nextIndex,
|
||||||
|
currentCopy: allCopies[nextIndex]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 隐藏加载动画
|
||||||
|
wx.hideLoading();
|
||||||
|
}, 300);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 一键发布(先领取,再发布)
|
// 一键发布(先领取,再发布)
|
||||||
@@ -281,6 +288,84 @@ Page({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 拒绝文案
|
||||||
|
async rejectArticle() {
|
||||||
|
if (!this.data.currentCopy) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请先选择文案',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wx.showModal({
|
||||||
|
title: '确认拒绝',
|
||||||
|
content: '确定要拒绝这篇文案吗?',
|
||||||
|
confirmText: '拒绝',
|
||||||
|
confirmColor: '#ff4d4f',
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
await this.doRejectArticle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 执行拒绝操作
|
||||||
|
async doRejectArticle() {
|
||||||
|
this.setData({ rejecting: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await EmployeeService.updateArticleStatus(
|
||||||
|
this.data.currentCopy.id,
|
||||||
|
'rejected'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.code === 200) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '已拒绝',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1500
|
||||||
|
});
|
||||||
|
|
||||||
|
// 从列表中移除当前文案
|
||||||
|
const { allCopies, currentIndex } = this.data;
|
||||||
|
allCopies.splice(currentIndex, 1);
|
||||||
|
|
||||||
|
// 更新显示
|
||||||
|
if (allCopies.length > 0) {
|
||||||
|
const newIndex = currentIndex >= allCopies.length ? 0 : currentIndex;
|
||||||
|
this.setData({
|
||||||
|
allCopies,
|
||||||
|
currentIndex: newIndex,
|
||||||
|
currentCopy: allCopies[newIndex],
|
||||||
|
rejecting: false
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 没有更多文案了
|
||||||
|
this.setData({
|
||||||
|
allCopies: [],
|
||||||
|
currentCopy: null,
|
||||||
|
rejecting: false
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
wx.navigateBack();
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(response.message || '拒绝失败');
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('拒绝失败:', error);
|
||||||
|
this.setData({ rejecting: false });
|
||||||
|
wx.showToast({
|
||||||
|
title: error.message || '操作失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// 分享到朋友圈
|
// 分享到朋友圈
|
||||||
onShareTimeline() {
|
onShareTimeline() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -53,16 +53,24 @@
|
|||||||
<!-- 底部操作栏 -->
|
<!-- 底部操作栏 -->
|
||||||
<view class="action-bar" wx:if="{{currentCopy}}">
|
<view class="action-bar" wx:if="{{currentCopy}}">
|
||||||
<button
|
<button
|
||||||
class="action-btn secondary"
|
class="action-btn refresh"
|
||||||
bindtap="changeArticle"
|
bindtap="changeArticle"
|
||||||
disabled="{{claiming || publishing}}"
|
disabled="{{claiming || publishing || rejecting}}"
|
||||||
>
|
>
|
||||||
<text class="btn-text">换一换</text>
|
<text class="btn-text">换一换</text>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="action-btn reject"
|
||||||
|
bindtap="rejectArticle"
|
||||||
|
disabled="{{claiming || publishing || rejecting}}"
|
||||||
|
loading="{{rejecting}}"
|
||||||
|
>
|
||||||
|
<text class="btn-text">{{rejecting ? '拒绝中...' : '拒绝'}}</text>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
class="action-btn primary"
|
class="action-btn primary"
|
||||||
bindtap="publishArticle"
|
bindtap="publishArticle"
|
||||||
disabled="{{claiming || publishing}}"
|
disabled="{{claiming || publishing || rejecting}}"
|
||||||
loading="{{claiming || publishing}}"
|
loading="{{claiming || publishing}}"
|
||||||
>
|
>
|
||||||
<text class="btn-text">{{claiming ? '领取中...' : (publishing ? '发布中...' : '一键发布')}}</text>
|
<text class="btn-text">{{claiming ? '领取中...' : (publishing ? '发布中...' : '一键发布')}}</text>
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ page {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20rpx;
|
gap: 16rpx;
|
||||||
padding: 20rpx 30rpx;
|
padding: 20rpx 30rpx;
|
||||||
background: white;
|
background: white;
|
||||||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
|
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||||
@@ -182,11 +182,11 @@ page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.action-btn {
|
.action-btn {
|
||||||
height: 80rpx;
|
height: 88rpx;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 40rpx;
|
border-radius: 44rpx;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -198,20 +198,34 @@ page {
|
|||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.secondary {
|
/* 换一换按钮 */
|
||||||
flex: 0 0 180rpx;
|
.action-btn.refresh {
|
||||||
|
flex: 0 0 220rpx;
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.secondary:active {
|
.action-btn.refresh:active {
|
||||||
background: #e8e8e8;
|
background: #e8e8e8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 拒绝按钮 */
|
||||||
|
.action-btn.reject {
|
||||||
|
flex: 0 0 180rpx;
|
||||||
|
background: linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.reject:active {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 一键发布按钮 */
|
||||||
.action-btn.primary {
|
.action-btn.primary {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background: #07c160;
|
background: linear-gradient(135deg, #07c160 0%, #0ae97a 100%);
|
||||||
color: white;
|
color: white;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(7, 193, 96, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.primary:active {
|
.action-btn.primary:active {
|
||||||
@@ -219,7 +233,7 @@ page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.action-btn[disabled] {
|
.action-btn[disabled] {
|
||||||
opacity: 0.6;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-icon {
|
.btn-icon {
|
||||||
|
|||||||
@@ -210,4 +210,13 @@ export class EmployeeService {
|
|||||||
publish_time: string;
|
publish_time: string;
|
||||||
}>(`/api/employee/publish-record/${recordId}`);
|
}>(`/api/employee/publish-record/${recordId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新文案状态(通过/拒绝)
|
||||||
|
*/
|
||||||
|
static async updateArticleStatus(articleId: number, status: 'approved' | 'rejected') {
|
||||||
|
return post(`/api/employee/article/${articleId}/status`, {
|
||||||
|
status
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user