礼金明细
+喜结良缘 · 礼尚往来
+{{ tip }}
+ +{{ tip }}
+ +diff --git a/hunliji-api/hl-api b/hunliji-api/hl-api index f4aa63d..431f24c 100644 Binary files a/hunliji-api/hl-api and b/hunliji-api/hl-api differ diff --git a/hunliji-api/main.go b/hunliji-api/main.go index 3821a55..f0973b4 100644 --- a/hunliji-api/main.go +++ b/hunliji-api/main.go @@ -37,6 +37,8 @@ func migrateSchema(db *gorm.DB) { {&models.SiteGift{}, "站点礼物", "site_gifts"}, {&models.GiftConfig{}, "礼物兑换配置", "gift_configs"}, {&models.AiModerationCache{}, "AI审核缓存", "ai_moderation_caches"}, + {&models.CashGift{}, "礼金记录", "cash_gifts"}, + {&models.CashGiftConfig{}, "礼金配置", "cash_gift_configs"}, {&visit.SiteVisit{}, "访客记录", "site_visits"}, } for _, t := range tables { diff --git a/hunliji-api/models/models.go b/hunliji-api/models/models.go index e85d3a5..d58299a 100644 --- a/hunliji-api/models/models.go +++ b/hunliji-api/models/models.go @@ -98,3 +98,26 @@ type AiModerationCache struct { } func (AiModerationCache) TableName() string { return "ai_moderation_caches" } + +// CashGift 礼金记录 +type CashGift struct { + ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` + Name string `gorm:"column:name;size:50;not null;default:'';index;comment:宾客姓名" json:"name"` + Amount int `gorm:"column:amount;not null;default:0;comment:礼金金额(元)" json:"amount"` + Note string `gorm:"column:note;size:255;not null;default:'';comment:备注" json:"note"` + CreatedAt time.Time `gorm:"column:created_at;not null;index;comment:登记时间" json:"created_at"` + UpdatedAt time.Time `gorm:"column:updated_at;comment:更新时间" json:"updated_at"` +} + +func (CashGift) TableName() string { return "cash_gifts" } + +// CashGiftConfig 礼金备注快捷选项等配置 +type CashGiftConfig struct { + ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` + NotesData string `gorm:"type:json;column:notes_data;not null;comment:备注快捷选项JSON数组" json:"notes_data"` + ViewPass string `gorm:"column:view_pass;size:64;not null;default:'';comment:前台查看全部口令" json:"view_pass"` + EntryPass string `gorm:"column:entry_pass;size:64;not null;default:'';comment:前台记账登记口令" json:"entry_pass"` + UpdatedAt time.Time `gorm:"column:updated_at;comment:更新时间" json:"updated_at"` +} + +func (CashGiftConfig) TableName() string { return "cash_gift_configs" } diff --git a/hunliji-api/router/routers.go b/hunliji-api/router/routers.go index 7fbc051..a652c55 100644 --- a/hunliji-api/router/routers.go +++ b/hunliji-api/router/routers.go @@ -10,6 +10,7 @@ import ( "mime/multipart" "net/url" "path/filepath" + "strconv" "strings" "time" @@ -204,6 +205,7 @@ func registerAPI(api *gin.RouterGroup) { api.POST("/ai/blessing", handleAIBlessing) api.POST("/rsvp", handleCreateRsvp) api.GET("/rsvp/list", handleRsvpList) + api.DELETE("/rsvp/:id", handleDeleteRsvp) api.GET("/danmaku", handlePublicDanmaku) api.POST("/danmaku", handleCreateDanmaku) api.GET("/danmaku/list", handleDanmakuList) @@ -215,6 +217,20 @@ func registerAPI(api *gin.RouterGroup) { api.GET("/gift/stats", handleGiftStats) api.GET("/gift/costs", handleGetGiftCosts) api.POST("/gift/costs", handleSaveGiftCosts) + api.POST("/cash-gift", handleCreateCashGift) + api.GET("/cash-gift/recent", handleCashGiftRecent) + api.GET("/cash-gift/notes", handleGetCashGiftNotes) + api.POST("/cash-gift/notes", handleSaveCashGiftNotes) + api.GET("/cash-gift/view-pass", handleGetCashGiftViewPass) + api.POST("/cash-gift/view-pass", handleSaveCashGiftViewPass) + api.POST("/cash-gift/view/unlock", handleCashGiftViewUnlock) + api.GET("/cash-gift/view/list", handleCashGiftViewList) + api.GET("/cash-gift/entry-pass", handleGetCashGiftEntryPass) + api.POST("/cash-gift/entry-pass", handleSaveCashGiftEntryPass) + api.POST("/cash-gift/entry/unlock", handleCashGiftEntryUnlock) + api.GET("/cash-gift/list", handleCashGiftList) + api.PUT("/cash-gift/:id", handleUpdateCashGift) + api.DELETE("/cash-gift/:id", handleDeleteCashGift) visit.Register(api, db, utils.RequireAdmin) configsection.Register(api, db, utils.RequireAdmin) @@ -416,6 +432,27 @@ func handleRsvpList(c *gin.Context) { c.JSON(200, gin.H{"code": 200, "data": list}) } +func handleDeleteRsvp(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + id := strings.TrimSpace(c.Param("id")) + if id == "" { + c.JSON(400, gin.H{"error": "缺少 ID"}) + return + } + res := db.Delete(&models.Rsvp{}, id) + if res.Error != nil { + c.JSON(500, gin.H{"error": "删除失败"}) + return + } + if res.RowsAffected == 0 { + c.JSON(404, gin.H{"error": "记录不存在"}) + return + } + c.JSON(200, gin.H{"code": 200, "msg": "已删除"}) +} + func handlePublicDanmaku(c *gin.Context) { q := db.Where("status = ?", "approved") if after := strings.TrimSpace(c.Query("after_id")); after != "" { @@ -960,3 +997,526 @@ func collectAlbumImages(configData string) []string { } return images } + +func handleCreateCashGift(c *gin.Context) { + if !requireCashGiftEntryAccess(c) { + return + } + var body struct { + Name string `json:"name"` + Amount int `json:"amount"` + Note string `json:"note"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(400, gin.H{"error": "参数错误"}) + return + } + name := strings.TrimSpace(body.Name) + note := strings.TrimSpace(body.Note) + if name == "" { + c.JSON(400, gin.H{"error": "请填写姓名"}) + return + } + if len([]rune(name)) > 50 { + c.JSON(400, gin.H{"error": "姓名过长"}) + return + } + if body.Amount <= 0 { + c.JSON(400, gin.H{"error": "请填写正确金额"}) + return + } + if body.Amount > 10000000 { + c.JSON(400, gin.H{"error": "金额过大"}) + return + } + if len([]rune(note)) > 200 { + c.JSON(400, gin.H{"error": "备注过长"}) + return + } + item := models.CashGift{ + Name: name, + Amount: body.Amount, + Note: note, + } + if err := db.Create(&item).Error; err != nil { + c.JSON(500, gin.H{"error": "保存失败"}) + return + } + c.JSON(200, gin.H{"code": 200, "msg": "已登记", "data": item}) +} + +func handleCashGiftRecent(c *gin.Context) { + if !requireCashGiftEntryAccess(c) { + return + } + limit := 3 + if v := strings.TrimSpace(c.Query("limit")); v != "" { + if n, err := strconv.Atoi(v); err == nil && n > 0 && n <= 20 { + limit = n + } + } + var list []models.CashGift + db.Order("created_at desc, id desc").Limit(limit).Find(&list) + c.JSON(200, gin.H{"code": 200, "data": list}) +} + +func defaultCashGiftNotes() []string { + return []string{ + "男方亲戚", "女方亲戚", + "男方朋友", "女方朋友", + "男方同学", "女方同学", + "男方同事", "女方同事", + "男方邻居", "女方邻居", + "其他", + } +} + +func normalizeCashGiftNotes(raw []string) []string { + seen := map[string]bool{} + out := make([]string, 0, len(raw)) + for _, s := range raw { + s = strings.TrimSpace(s) + if s == "" || seen[s] { + continue + } + if len([]rune(s)) > 30 { + s = string([]rune(s)[:30]) + } + seen[s] = true + out = append(out, s) + if len(out) >= 40 { + break + } + } + return out +} + +func loadCashGiftNotes() []string { + var cfg models.CashGiftConfig + if err := db.First(&cfg, 1).Error; err != nil || strings.TrimSpace(cfg.NotesData) == "" { + return defaultCashGiftNotes() + } + var notes []string + if err := json.Unmarshal([]byte(cfg.NotesData), ¬es); err != nil { + return defaultCashGiftNotes() + } + notes = normalizeCashGiftNotes(notes) + if len(notes) == 0 { + return defaultCashGiftNotes() + } + return notes +} + +func saveCashGiftNotes(notes []string) error { + notes = normalizeCashGiftNotes(notes) + if len(notes) == 0 { + notes = defaultCashGiftNotes() + } + raw, err := json.Marshal(notes) + if err != nil { + return err + } + var cfg models.CashGiftConfig + if err := db.First(&cfg, 1).Error; err != nil { + cfg = models.CashGiftConfig{ID: 1, NotesData: string(raw)} + return db.Create(&cfg).Error + } + cfg.NotesData = string(raw) + return db.Save(&cfg).Error +} + +func loadCashGiftViewPass() string { + var cfg models.CashGiftConfig + if err := db.First(&cfg, 1).Error; err != nil { + return "" + } + return strings.TrimSpace(cfg.ViewPass) +} + +func loadCashGiftEntryPass() string { + var cfg models.CashGiftConfig + if err := db.First(&cfg, 1).Error; err != nil { + return "" + } + return strings.TrimSpace(cfg.EntryPass) +} + +func saveCashGiftViewPass(pass string) error { + pass = strings.TrimSpace(pass) + if len([]rune(pass)) > 64 { + pass = string([]rune(pass)[:64]) + } + var cfg models.CashGiftConfig + if err := db.First(&cfg, 1).Error; err != nil { + notes, _ := json.Marshal(defaultCashGiftNotes()) + cfg = models.CashGiftConfig{ID: 1, NotesData: string(notes), ViewPass: pass} + return db.Create(&cfg).Error + } + cfg.ViewPass = pass + return db.Save(&cfg).Error +} + +func saveCashGiftEntryPass(pass string) error { + pass = strings.TrimSpace(pass) + if len([]rune(pass)) > 64 { + pass = string([]rune(pass)[:64]) + } + var cfg models.CashGiftConfig + if err := db.First(&cfg, 1).Error; err != nil { + notes, _ := json.Marshal(defaultCashGiftNotes()) + cfg = models.CashGiftConfig{ID: 1, NotesData: string(notes), EntryPass: pass} + return db.Create(&cfg).Error + } + cfg.EntryPass = pass + return db.Save(&cfg).Error +} + +func cashGiftViewTokenFromRequest(c *gin.Context) string { + if t := strings.TrimSpace(c.GetHeader("X-Cash-Gift-Token")); t != "" { + return t + } + return utils.BearerToken(c) +} + +func cashGiftEntryTokenFromRequest(c *gin.Context) string { + if t := strings.TrimSpace(c.GetHeader("X-Cash-Gift-Entry-Token")); t != "" { + return t + } + return utils.BearerToken(c) +} + +func requireCashGiftViewAccess(c *gin.Context) bool { + token := cashGiftViewTokenFromRequest(c) + if utils.VerifyCashGiftViewToken(token) { + return true + } + if utils.VerifyToken(token) { + return true + } + c.JSON(403, gin.H{"error": "请先输入查看口令"}) + return false +} + +func requireCashGiftEntryAccess(c *gin.Context) bool { + token := cashGiftEntryTokenFromRequest(c) + if utils.VerifyCashGiftEntryToken(token) { + return true + } + if utils.VerifyToken(token) { + return true + } + c.JSON(403, gin.H{"error": "请先输入记账口令"}) + return false +} + +func handleGetCashGiftViewPass(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + pass := loadCashGiftViewPass() + c.JSON(200, gin.H{ + "code": 200, + "data": gin.H{ + "has_pass": pass != "", + "password": pass, + }, + }) +} + +func handleSaveCashGiftViewPass(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + var body struct { + Password string `json:"password"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(400, gin.H{"error": "参数错误"}) + return + } + pass := strings.TrimSpace(body.Password) + if pass == "" { + c.JSON(400, gin.H{"error": "请设置查看口令"}) + return + } + if err := saveCashGiftViewPass(pass); err != nil { + c.JSON(500, gin.H{"error": "保存失败"}) + return + } + c.JSON(200, gin.H{"code": 200, "msg": "口令已保存", "data": gin.H{"has_pass": true}}) +} + +func handleCashGiftViewUnlock(c *gin.Context) { + var body struct { + Password string `json:"password"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(400, gin.H{"error": "参数错误"}) + return + } + pass := loadCashGiftViewPass() + if pass == "" { + c.JSON(403, gin.H{"error": "尚未配置查看口令,请先在后台设置"}) + return + } + if strings.TrimSpace(body.Password) != pass { + c.JSON(403, gin.H{"error": "口令错误"}) + return + } + c.JSON(200, gin.H{ + "code": 200, + "msg": "已解锁", + "data": gin.H{"token": utils.SignCashGiftViewToken()}, + }) +} + +func handleGetCashGiftEntryPass(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + pass := loadCashGiftEntryPass() + c.JSON(200, gin.H{ + "code": 200, + "data": gin.H{ + "has_pass": pass != "", + "password": pass, + }, + }) +} + +func handleSaveCashGiftEntryPass(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + var body struct { + Password string `json:"password"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(400, gin.H{"error": "参数错误"}) + return + } + pass := strings.TrimSpace(body.Password) + if pass == "" { + c.JSON(400, gin.H{"error": "请设置记账口令"}) + return + } + if err := saveCashGiftEntryPass(pass); err != nil { + c.JSON(500, gin.H{"error": "保存失败"}) + return + } + c.JSON(200, gin.H{"code": 200, "msg": "口令已保存", "data": gin.H{"has_pass": true}}) +} + +func handleCashGiftEntryUnlock(c *gin.Context) { + var body struct { + Password string `json:"password"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(400, gin.H{"error": "参数错误"}) + return + } + pass := loadCashGiftEntryPass() + if pass == "" { + c.JSON(403, gin.H{"error": "尚未配置记账口令,请先在后台设置"}) + return + } + if strings.TrimSpace(body.Password) != pass { + c.JSON(403, gin.H{"error": "口令错误"}) + return + } + c.JSON(200, gin.H{ + "code": 200, + "msg": "已解锁", + "data": gin.H{"token": utils.SignCashGiftEntryToken()}, + }) +} + +func handleCashGiftViewList(c *gin.Context) { + if !requireCashGiftViewAccess(c) { + return + } + q := strings.TrimSpace(c.Query("q")) + note := strings.TrimSpace(c.Query("note")) + side := strings.TrimSpace(c.Query("side")) // male | female | other | "" + sortKey := strings.TrimSpace(c.Query("sort")) + minAmount := 0 + maxAmount := 0 + if v := strings.TrimSpace(c.Query("min")); v != "" { + if n, err := strconv.Atoi(v); err == nil && n > 0 { + minAmount = n + } + } + if v := strings.TrimSpace(c.Query("max")); v != "" { + if n, err := strconv.Atoi(v); err == nil && n > 0 { + maxAmount = n + } + } + + tx := db.Model(&models.CashGift{}) + if q != "" { + like := "%" + q + "%" + tx = tx.Where("name LIKE ? OR note LIKE ?", like, like) + } + if note != "" { + tx = tx.Where("note = ?", note) + } + switch side { + case "male": + tx = tx.Where("note LIKE ?", "男方%") + case "female": + tx = tx.Where("note LIKE ?", "女方%") + case "other": + tx = tx.Where("note NOT LIKE ? AND note NOT LIKE ? AND note <> ''", "男方%", "女方%") + } + if minAmount > 0 { + tx = tx.Where("amount >= ?", minAmount) + } + if maxAmount > 0 { + tx = tx.Where("amount <= ?", maxAmount) + } + + order := "created_at desc, id desc" + switch sortKey { + case "time_asc": + order = "created_at asc, id asc" + case "amount_desc": + order = "amount desc, created_at desc" + case "amount_asc": + order = "amount asc, created_at desc" + case "name_asc": + order = "name asc, created_at desc" + } + + var list []models.CashGift + tx.Order(order).Find(&list) + total := 0 + for _, it := range list { + total += it.Amount + } + c.JSON(200, gin.H{ + "code": 200, + "data": gin.H{ + "list": list, + "total": total, + "count": len(list), + "notes": loadCashGiftNotes(), + }, + }) +} + +func handleGetCashGiftNotes(c *gin.Context) { + c.JSON(200, gin.H{ + "code": 200, + "data": gin.H{ + "notes": loadCashGiftNotes(), + "defaults": defaultCashGiftNotes(), + }, + }) +} + +func handleSaveCashGiftNotes(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + var body struct { + Notes []string `json:"notes"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(400, gin.H{"error": "参数错误"}) + return + } + notes := normalizeCashGiftNotes(body.Notes) + if len(notes) == 0 { + c.JSON(400, gin.H{"error": "至少保留一个快捷备注"}) + return + } + if err := saveCashGiftNotes(notes); err != nil { + c.JSON(500, gin.H{"error": "保存失败"}) + return + } + c.JSON(200, gin.H{"code": 200, "msg": "已保存", "data": gin.H{"notes": notes}}) +} + +func handleCashGiftList(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + var list []models.CashGift + db.Order("created_at desc, id desc").Find(&list) + total := 0 + for _, it := range list { + total += it.Amount + } + c.JSON(200, gin.H{ + "code": 200, + "data": gin.H{ + "list": list, + "total": total, + "count": len(list), + }, + }) +} + +func handleUpdateCashGift(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + id, err := strconv.ParseUint(strings.TrimSpace(c.Param("id")), 10, 64) + if err != nil || id == 0 { + c.JSON(400, gin.H{"error": "无效 ID"}) + return + } + var body struct { + Name string `json:"name"` + Amount int `json:"amount"` + Note string `json:"note"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(400, gin.H{"error": "参数错误"}) + return + } + name := strings.TrimSpace(body.Name) + note := strings.TrimSpace(body.Note) + if name == "" { + c.JSON(400, gin.H{"error": "请填写姓名"}) + return + } + if body.Amount <= 0 { + c.JSON(400, gin.H{"error": "请填写正确金额"}) + return + } + var item models.CashGift + if err := db.First(&item, id).Error; err != nil { + c.JSON(404, gin.H{"error": "记录不存在"}) + return + } + item.Name = name + item.Amount = body.Amount + item.Note = note + if err := db.Save(&item).Error; err != nil { + c.JSON(500, gin.H{"error": "保存失败"}) + return + } + c.JSON(200, gin.H{"code": 200, "msg": "已更新", "data": item}) +} + +func handleDeleteCashGift(c *gin.Context) { + if !utils.RequireAdmin(c) { + return + } + id := strings.TrimSpace(c.Param("id")) + if id == "" { + c.JSON(400, gin.H{"error": "缺少 ID"}) + return + } + res := db.Delete(&models.CashGift{}, id) + if res.Error != nil { + c.JSON(500, gin.H{"error": "删除失败"}) + return + } + if res.RowsAffected == 0 { + c.JSON(404, gin.H{"error": "记录不存在"}) + return + } + c.JSON(200, gin.H{"code": 200, "msg": "已删除"}) +} diff --git a/hunliji-api/utils/utils.go b/hunliji-api/utils/utils.go index 906a66a..21a371d 100644 --- a/hunliji-api/utils/utils.go +++ b/hunliji-api/utils/utils.go @@ -38,29 +38,65 @@ func SignToken(account string) string { return b64 + "." + sig } -func VerifyToken(token string) bool { +func SignCashGiftViewToken() string { + payload := fmt.Sprintf(`{"account":%q,"exp":%d}`, "cash-gift-view", time.Now().Add(7*24*time.Hour).Unix()) + b64 := base64.StdEncoding.EncodeToString([]byte(payload)) + mac := hmac.New(sha256.New, []byte(adminSecret)) + mac.Write([]byte(b64)) + sig := base64.StdEncoding.EncodeToString(mac.Sum(nil)) + return b64 + "." + sig +} + +func SignCashGiftEntryToken() string { + payload := fmt.Sprintf(`{"account":%q,"exp":%d}`, "cash-gift-entry", time.Now().Add(7*24*time.Hour).Unix()) + b64 := base64.StdEncoding.EncodeToString([]byte(payload)) + mac := hmac.New(sha256.New, []byte(adminSecret)) + mac.Write([]byte(b64)) + sig := base64.StdEncoding.EncodeToString(mac.Sum(nil)) + return b64 + "." + sig +} + +func parseTokenClaims(token string) (account string, exp int64, ok bool) { parts := strings.Split(token, ".") if len(parts) != 2 { - return false + return "", 0, false } mac := hmac.New(sha256.New, []byte(adminSecret)) mac.Write([]byte(parts[0])) expected := base64.StdEncoding.EncodeToString(mac.Sum(nil)) if !hmac.Equal([]byte(expected), []byte(parts[1])) { - return false + return "", 0, false } raw, err := base64.StdEncoding.DecodeString(parts[0]) if err != nil { - return false + return "", 0, false } var claims struct { Account string `json:"account"` Exp int64 `json:"exp"` } if err := json.Unmarshal(raw, &claims); err != nil { - return false + return "", 0, false } - return time.Now().Unix() <= claims.Exp + if time.Now().Unix() > claims.Exp { + return "", 0, false + } + return claims.Account, claims.Exp, true +} + +func VerifyToken(token string) bool { + _, _, ok := parseTokenClaims(token) + return ok +} + +func VerifyCashGiftViewToken(token string) bool { + account, _, ok := parseTokenClaims(token) + return ok && account == "cash-gift-view" +} + +func VerifyCashGiftEntryToken(token string) bool { + account, _, ok := parseTokenClaims(token) + return ok && account == "cash-gift-entry" } func BearerToken(c *gin.Context) string { @@ -79,7 +115,7 @@ func CORSMiddleware() gin.HandlerFunc { return func(c *gin.Context) { c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT") - c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") + c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Cash-Gift-Token, X-Cash-Gift-Entry-Token") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(204) return diff --git a/vite-tailwindcss/index.html b/vite-tailwindcss/index.html index 66bd934..c02fc21 100644 --- a/vite-tailwindcss/index.html +++ b/vite-tailwindcss/index.html @@ -2,7 +2,8 @@
- + + diff --git a/vite-tailwindcss/src/api/wedding.js b/vite-tailwindcss/src/api/wedding.js index 60adaf6..56f4838 100644 --- a/vite-tailwindcss/src/api/wedding.js +++ b/vite-tailwindcss/src/api/wedding.js @@ -162,6 +162,72 @@ export function saveGiftCosts(costs) { return service.post('/gift/costs', { costs }) } +export function submitCashGift(form, entryToken = '') { + const headers = {} + if (entryToken) headers['X-Cash-Gift-Entry-Token'] = entryToken + return service.post('/cash-gift', form, { headers }) +} + +export function getCashGiftRecent(limit = 3, entryToken = '') { + const headers = {} + if (entryToken) headers['X-Cash-Gift-Entry-Token'] = entryToken + return service.get('/cash-gift/recent', { params: { limit }, headers }) +} + +export function getCashGiftNotes() { + return service.get('/cash-gift/notes') +} + +export function saveCashGiftNotes(notes) { + return service.post('/cash-gift/notes', { notes }) +} + +export function getCashGiftViewPass() { + return service.get('/cash-gift/view-pass') +} + +export function saveCashGiftViewPass(password) { + return service.post('/cash-gift/view-pass', { password }) +} + +export function unlockCashGiftView(password) { + return service.post('/cash-gift/view/unlock', { password }) +} + +export function getCashGiftEntryPass() { + return service.get('/cash-gift/entry-pass') +} + +export function saveCashGiftEntryPass(password) { + return service.post('/cash-gift/entry-pass', { password }) +} + +export function unlockCashGiftEntry(password) { + return service.post('/cash-gift/entry/unlock', { password }) +} + +export function getCashGiftViewList(params = {}, token = '') { + const headers = {} + if (token) headers['X-Cash-Gift-Token'] = token + return service.get('/cash-gift/view/list', { params, headers }) +} + +export function getCashGiftList() { + return service.get('/cash-gift/list') +} + +export function updateCashGift(id, form) { + return service.put(`/cash-gift/${id}`, form) +} + +export function deleteCashGift(id) { + return service.delete(`/cash-gift/${id}`) +} + +export function deleteRsvp(id) { + return service.delete(`/rsvp/${id}`) +} + export function adminLogin(credentials) { return service.post('/admin/login', credentials) } diff --git a/vite-tailwindcss/src/components/DanmakuLayer.vue b/vite-tailwindcss/src/components/DanmakuLayer.vue index eac121a..f884a60 100644 --- a/vite-tailwindcss/src/components/DanmakuLayer.vue +++ b/vite-tailwindcss/src/components/DanmakuLayer.vue @@ -1,6 +1,11 @@ -