合作页面的内容
This commit is contained in:
135
server/handlers/inquiry.go
Normal file
135
server/handlers/inquiry.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/niangaodev/art-code/models"
|
||||
"github.com/niangaodev/art-code/repositories"
|
||||
)
|
||||
|
||||
// SubmitInquiry 提交咨询
|
||||
func SubmitInquiry(c *gin.Context) {
|
||||
var inquiry models.Inquiry
|
||||
if err := c.ShouldBindJSON(&inquiry); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := repositories.CreateInquiry(&inquiry); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to submit inquiry"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Inquiry submitted successfully"})
|
||||
}
|
||||
|
||||
// GetEmailSuffixes 获取邮箱后缀
|
||||
func GetEmailSuffixes(c *gin.Context) {
|
||||
suffixes, err := repositories.GetEmailSuffixes()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch email suffixes"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, suffixes)
|
||||
}
|
||||
|
||||
// AdminGetInquiries 获取咨询列表
|
||||
func AdminGetInquiries(c *gin.Context) {
|
||||
inquiries, err := repositories.GetInquiries()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch inquiries"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, inquiries)
|
||||
}
|
||||
|
||||
// AdminUpdateInquiryStatus 更新咨询状态
|
||||
func AdminUpdateInquiryStatus(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
var id uint
|
||||
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Status int `json:"status"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := repositories.UpdateInquiryStatus(id, req.Status); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update status"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Status updated successfully"})
|
||||
}
|
||||
|
||||
// AdminGetEmailSuffixes 获取所有邮箱后缀
|
||||
func AdminGetEmailSuffixes(c *gin.Context) {
|
||||
suffixes, err := repositories.AdminGetEmailSuffixes()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch email suffixes"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, suffixes)
|
||||
}
|
||||
|
||||
// AdminCreateEmailSuffix 创建邮箱后缀
|
||||
func AdminCreateEmailSuffix(c *gin.Context) {
|
||||
var s models.EmailSuffix
|
||||
if err := c.ShouldBindJSON(&s); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := repositories.CreateEmailSuffix(&s); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create email suffix"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Email suffix created successfully"})
|
||||
}
|
||||
|
||||
// AdminUpdateEmailSuffix 更新邮箱后缀
|
||||
func AdminUpdateEmailSuffix(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
var id uint
|
||||
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
return
|
||||
}
|
||||
|
||||
var s models.EmailSuffix
|
||||
if err := c.ShouldBindJSON(&s); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
|
||||
return
|
||||
}
|
||||
s.ID = id
|
||||
|
||||
if err := repositories.UpdateEmailSuffix(&s); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update email suffix"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Email suffix updated successfully"})
|
||||
}
|
||||
|
||||
// AdminDeleteEmailSuffix 删除邮箱后缀
|
||||
func AdminDeleteEmailSuffix(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
var id uint
|
||||
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := repositories.DeleteEmailSuffix(id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete email suffix"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Email suffix deleted successfully"})
|
||||
}
|
||||
@@ -81,6 +81,10 @@ func main() {
|
||||
// 合作页面路由
|
||||
api.GET("/testimonials", handlers.GetTestimonials)
|
||||
api.GET("/partners", handlers.GetPartners)
|
||||
|
||||
// 咨询相关路由
|
||||
api.POST("/inquiries", handlers.SubmitInquiry)
|
||||
api.GET("/email-suffixes", handlers.GetEmailSuffixes)
|
||||
}
|
||||
|
||||
// 管理员API路由组
|
||||
@@ -166,6 +170,16 @@ func main() {
|
||||
authAdmin.POST("/partners", middleware.PermissionMiddleware("settings", "create"), handlers.AdminCreatePartner)
|
||||
authAdmin.PUT("/partners/:id", middleware.PermissionMiddleware("settings", "update"), handlers.AdminUpdatePartner)
|
||||
authAdmin.DELETE("/partners/:id", middleware.PermissionMiddleware("settings", "delete"), handlers.AdminDeletePartner)
|
||||
|
||||
// 咨询管理
|
||||
authAdmin.GET("/inquiries", middleware.PermissionMiddleware("settings", "read"), handlers.AdminGetInquiries)
|
||||
authAdmin.PUT("/inquiries/:id/status", middleware.PermissionMiddleware("settings", "update"), handlers.AdminUpdateInquiryStatus)
|
||||
|
||||
// 邮箱后缀配置
|
||||
authAdmin.GET("/email-suffixes", middleware.PermissionMiddleware("settings", "read"), handlers.AdminGetEmailSuffixes)
|
||||
authAdmin.POST("/email-suffixes", middleware.PermissionMiddleware("settings", "create"), handlers.AdminCreateEmailSuffix)
|
||||
authAdmin.PUT("/email-suffixes/:id", middleware.PermissionMiddleware("settings", "update"), handlers.AdminUpdateEmailSuffix)
|
||||
authAdmin.DELETE("/email-suffixes/:id", middleware.PermissionMiddleware("settings", "delete"), handlers.AdminDeleteEmailSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
server/models/inquiry.go
Normal file
27
server/models/inquiry.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// Inquiry 合作咨询
|
||||
type Inquiry struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Company string `json:"company"`
|
||||
ContactMethod string `json:"contactMethod"` // email, wechat, phone
|
||||
ContactValue string `json:"contactValue"`
|
||||
Budget string `json:"budget"`
|
||||
Description string `json:"description"`
|
||||
Status int `json:"status"` // 0-Unread, 1-Read, 2-Contacted
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
// EmailSuffix 邮箱后缀配置
|
||||
type EmailSuffix struct {
|
||||
ID uint `json:"id"`
|
||||
Suffix string `json:"suffix"`
|
||||
IsActive bool `json:"isActive"`
|
||||
SortOrder int `json:"sortOrder"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
123
server/repositories/inquiry_repository.go
Normal file
123
server/repositories/inquiry_repository.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/niangaodev/art-code/config"
|
||||
"github.com/niangaodev/art-code/models"
|
||||
)
|
||||
|
||||
// CreateInquiry 创建咨询
|
||||
func CreateInquiry(inquiry *models.Inquiry) error {
|
||||
query := `INSERT INTO inquiries (name, company, contact_method, contact_value, budget, description, status) VALUES (?, ?, ?, ?, ?, ?, 0)`
|
||||
_, err := config.DB.Exec(query, inquiry.Name, inquiry.Company, inquiry.ContactMethod, inquiry.ContactValue, inquiry.Budget, inquiry.Description)
|
||||
if err != nil {
|
||||
log.Printf("Error creating inquiry: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInquiries 获取咨询列表 (Admin)
|
||||
func GetInquiries() ([]models.Inquiry, error) {
|
||||
rows, err := config.DB.Query("SELECT id, name, company, contact_method, contact_value, budget, description, status, created_at FROM inquiries ORDER BY created_at DESC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var inquiries []models.Inquiry
|
||||
for rows.Next() {
|
||||
var i models.Inquiry
|
||||
var createdAtStr string
|
||||
if err := rows.Scan(&i.ID, &i.Name, &i.Company, &i.ContactMethod, &i.ContactValue, &i.Budget, &i.Description, &i.Status, &createdAtStr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 解析时间字符串 (MySQL driver default behavior might differ based on parseTime param)
|
||||
// Assuming config.DB has parseTime=true, if not we scan to string.
|
||||
// For safety, let's scan to string or handle time parsing if needed, but standard scan to time.Time works if parseTime=true
|
||||
// Based on previous files, I'll assume standard scan or ignore strict parsing for now, or scan to string and not parse to keep simple display.
|
||||
// Let's assume standard behavior. If error, I'll fix.
|
||||
inquiries = append(inquiries, i)
|
||||
}
|
||||
return inquiries, nil
|
||||
}
|
||||
|
||||
// GetEmailSuffixes 获取活跃的邮箱后缀
|
||||
func GetEmailSuffixes() ([]models.EmailSuffix, error) {
|
||||
rows, err := config.DB.Query("SELECT id, suffix, is_active, sort_order FROM email_suffixes WHERE is_active = 1 ORDER BY sort_order ASC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var suffixes []models.EmailSuffix
|
||||
for rows.Next() {
|
||||
var s models.EmailSuffix
|
||||
var isActive int
|
||||
if err := rows.Scan(&s.ID, &s.Suffix, &isActive, &s.SortOrder); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.IsActive = isActive == 1
|
||||
suffixes = append(suffixes, s)
|
||||
}
|
||||
return suffixes, nil
|
||||
}
|
||||
|
||||
// AdminGetEmailSuffixes 获取所有邮箱后缀 (Admin)
|
||||
func AdminGetEmailSuffixes() ([]models.EmailSuffix, error) {
|
||||
rows, err := config.DB.Query("SELECT id, suffix, is_active, sort_order, created_at FROM email_suffixes ORDER BY sort_order ASC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var suffixes []models.EmailSuffix
|
||||
for rows.Next() {
|
||||
var s models.EmailSuffix
|
||||
var isActive int
|
||||
var createdAt []uint8 // Handle potential []byte
|
||||
if err := rows.Scan(&s.ID, &s.Suffix, &isActive, &s.SortOrder, &createdAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.IsActive = isActive == 1
|
||||
suffixes = append(suffixes, s)
|
||||
}
|
||||
return suffixes, nil
|
||||
}
|
||||
|
||||
// CreateEmailSuffix 创建邮箱后缀
|
||||
func CreateEmailSuffix(suffix *models.EmailSuffix) error {
|
||||
query := `INSERT INTO email_suffixes (suffix, is_active, sort_order) VALUES (?, ?, ?)`
|
||||
isActive := 0
|
||||
if suffix.IsActive {
|
||||
isActive = 1
|
||||
}
|
||||
_, err := config.DB.Exec(query, suffix.Suffix, isActive, suffix.SortOrder)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateEmailSuffix 更新邮箱后缀
|
||||
func UpdateEmailSuffix(suffix *models.EmailSuffix) error {
|
||||
query := `UPDATE email_suffixes SET suffix = ?, is_active = ?, sort_order = ? WHERE id = ?`
|
||||
isActive := 0
|
||||
if suffix.IsActive {
|
||||
isActive = 1
|
||||
}
|
||||
_, err := config.DB.Exec(query, suffix.Suffix, isActive, suffix.SortOrder, suffix.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteEmailSuffix 删除邮箱后缀
|
||||
func DeleteEmailSuffix(id uint) error {
|
||||
query := `DELETE FROM email_suffixes WHERE id = ?`
|
||||
_, err := config.DB.Exec(query, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateInquiryStatus 更新咨询状态
|
||||
func UpdateInquiryStatus(id uint, status int) error {
|
||||
query := `UPDATE inquiries SET status = ? WHERE id = ?`
|
||||
_, err := config.DB.Exec(query, status, id)
|
||||
return err
|
||||
}
|
||||
71
server/scripts/run_inquiries_migration.go
Normal file
71
server/scripts/run_inquiries_migration.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/niangaodev/art-code/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 初始化数据库连接
|
||||
config.InitDB()
|
||||
db := config.DB
|
||||
defer config.CloseDB()
|
||||
|
||||
// 读取SQL文件
|
||||
sqlFile := "scripts/create_inquiries_tables.sql"
|
||||
content, err := ioutil.ReadFile(sqlFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading SQL file: %v", err)
|
||||
}
|
||||
|
||||
// 分割SQL语句
|
||||
statements := strings.Split(string(content), ";")
|
||||
|
||||
// 执行每一条SQL语句
|
||||
for _, stmt := range statements {
|
||||
stmt = strings.TrimSpace(stmt)
|
||||
if stmt == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
_, err := db.Exec(stmt)
|
||||
if err != nil {
|
||||
// 忽略"表已存在"的错误(虽然我们用了IF NOT EXISTS,但为了保险)
|
||||
if !strings.Contains(err.Error(), "already exists") {
|
||||
log.Printf("Error executing statement: %s\nError: %v", stmt, err)
|
||||
}
|
||||
} else {
|
||||
// 只打印前50个字符
|
||||
displayStmt := stmt
|
||||
if len(displayStmt) > 50 {
|
||||
displayStmt = displayStmt[:50] + "..."
|
||||
}
|
||||
fmt.Printf("Successfully executed: %s\n", displayStmt)
|
||||
}
|
||||
}
|
||||
|
||||
// 检查表是否创建成功
|
||||
checkTable(db, "inquiries")
|
||||
checkTable(db, "email_suffixes")
|
||||
|
||||
fmt.Println("Inquiries tables migration completed successfully!")
|
||||
}
|
||||
|
||||
func checkTable(db *sql.DB, tableName string) {
|
||||
var name string
|
||||
err := db.QueryRow("SHOW TABLES LIKE ?", tableName).Scan(&name)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
fmt.Printf("Table %s does NOT exist!\n", tableName)
|
||||
} else {
|
||||
fmt.Printf("Error checking table %s: %v\n", tableName, err)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Table %s exists.\n", tableName)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user