diff --git a/.DS_Store b/.DS_Store
index 8eb634c..257f8cb 100755
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/.agents/README.md b/.agents/README.md
new file mode 100644
index 0000000..551f06d
--- /dev/null
+++ b/.agents/README.md
@@ -0,0 +1,38 @@
+# .agents Directory
+
+This directory contains agent configuration and skills for OpenAI Codex CLI.
+
+## Structure
+
+```
+.agents/
+ config.toml # Main configuration file
+ skills/ # Skill definitions
+ skill-name/
+ SKILL.md # Skill instructions
+ scripts/ # Optional scripts
+ docs/ # Optional documentation
+ README.md # This file
+```
+
+## Configuration
+
+The `config.toml` file controls:
+- Model selection
+- Approval policies
+- Sandbox modes
+- MCP server connections
+- Skills configuration
+
+## Skills
+
+Skills are invoked using `$skill-name` syntax. Each skill has:
+- YAML frontmatter with metadata
+- Trigger and skip conditions
+- Commands and examples
+
+## Documentation
+
+- Main instructions: `AGENTS.md` (project root)
+- Local overrides: `.codex/AGENTS.override.md` (gitignored)
+- Claude Flow: https://github.com/ruvnet/claude-flow
diff --git a/.agents/config.toml b/.agents/config.toml
new file mode 100644
index 0000000..9110b8e
--- /dev/null
+++ b/.agents/config.toml
@@ -0,0 +1,298 @@
+# =============================================================================
+# Claude Flow V3 - Codex Configuration
+# =============================================================================
+# Generated by: @claude-flow/codex
+# Documentation: https://github.com/ruvnet/claude-flow
+#
+# This file configures the Codex CLI for Claude Flow integration.
+# Place in .agents/config.toml (project) or .codex/config.toml (user).
+# =============================================================================
+
+# =============================================================================
+# Core Settings
+# =============================================================================
+
+# Model selection - the AI model to use for code generation
+# Options: gpt-5.3-codex, gpt-4o, claude-sonnet, claude-opus
+model = "gpt-5.3-codex"
+
+# Approval policy determines when human approval is required
+# - untrusted: Always require approval
+# - on-failure: Require approval only after failures
+# - on-request: Require approval for significant changes
+# - never: Auto-approve all actions (use with caution)
+approval_policy = "on-request"
+
+# Sandbox mode controls file system access
+# - read-only: Can only read files, no modifications
+# - workspace-write: Can write within workspace directory
+# - danger-full-access: Full file system access (dangerous)
+sandbox_mode = "workspace-write"
+
+# Web search enables internet access for research
+# - disabled: No web access
+# - cached: Use cached results when available
+# - live: Always fetch fresh results
+web_search = "cached"
+
+# =============================================================================
+# Project Documentation
+# =============================================================================
+
+# Maximum bytes to read from AGENTS.md files
+project_doc_max_bytes = 65536
+
+# Fallback filenames if AGENTS.md not found
+project_doc_fallback_filenames = [
+ "AGENTS.md",
+ "TEAM_GUIDE.md",
+ ".agents.md"
+]
+
+# =============================================================================
+# Features
+# =============================================================================
+
+[features]
+# Enable child AGENTS.md guidance
+child_agents_md = true
+
+# Cache shell environment for faster repeated commands
+shell_snapshot = true
+
+# Smart approvals based on request context
+request_rule = true
+
+# Enable remote compaction for large histories
+remote_compaction = true
+
+# =============================================================================
+# MCP Servers
+# =============================================================================
+
+[mcp_servers.claude-flow]
+command = "npx"
+args = ["-y", "@claude-flow/cli@latest"]
+enabled = true
+tool_timeout_sec = 120
+
+# =============================================================================
+# Skills Configuration
+# =============================================================================
+
+[[skills.config]]
+path = ".agents/skills/swarm-orchestration"
+enabled = true
+
+[[skills.config]]
+path = ".agents/skills/memory-management"
+enabled = true
+
+[[skills.config]]
+path = ".agents/skills/sparc-methodology"
+enabled = true
+
+[[skills.config]]
+path = ".agents/skills/security-audit"
+enabled = true
+
+# =============================================================================
+# Profiles
+# =============================================================================
+
+# Development profile - more permissive for local work
+[profiles.dev]
+approval_policy = "never"
+sandbox_mode = "danger-full-access"
+web_search = "live"
+
+# Safe profile - maximum restrictions
+[profiles.safe]
+approval_policy = "untrusted"
+sandbox_mode = "read-only"
+web_search = "disabled"
+
+# CI profile - for automated pipelines
+[profiles.ci]
+approval_policy = "never"
+sandbox_mode = "workspace-write"
+web_search = "cached"
+
+# =============================================================================
+# History
+# =============================================================================
+
+[history]
+# Save all session transcripts
+persistence = "save-all"
+
+# =============================================================================
+# Shell Environment
+# =============================================================================
+
+[shell_environment_policy]
+# Inherit environment variables
+inherit = "core"
+
+# Exclude sensitive variables
+exclude = ["*_KEY", "*_SECRET", "*_TOKEN", "*_PASSWORD"]
+
+# =============================================================================
+# Sandbox Workspace Write Settings
+# =============================================================================
+
+[sandbox_workspace_write]
+# Additional writable paths beyond workspace
+writable_roots = []
+
+# Allow network access
+network_access = true
+
+# Exclude temp directories
+exclude_slash_tmp = false
+
+# =============================================================================
+# Security Settings
+# =============================================================================
+
+[security]
+# Enable input validation for all user inputs
+input_validation = true
+
+# Prevent directory traversal attacks
+path_traversal_prevention = true
+
+# Scan for hardcoded secrets
+secret_scanning = true
+
+# Scan dependencies for known CVEs
+cve_scanning = true
+
+# Maximum file size for operations (bytes)
+max_file_size = 10485760
+
+# Allowed file extensions (empty = allow all)
+allowed_extensions = []
+
+# Blocked file patterns (regex)
+blocked_patterns = ["\\.env$", "credentials\\.json$", "\\.pem$", "\\.key$"]
+
+# =============================================================================
+# Performance Settings
+# =============================================================================
+
+[performance]
+# Maximum concurrent agents
+max_agents = 8
+
+# Task timeout in seconds
+task_timeout = 300
+
+# Memory limit per agent
+memory_limit = "512MB"
+
+# Enable response caching
+cache_enabled = true
+
+# Cache TTL in seconds
+cache_ttl = 3600
+
+# Enable parallel task execution
+parallel_execution = true
+
+# =============================================================================
+# Logging Settings
+# =============================================================================
+
+[logging]
+# Log level: debug, info, warn, error
+level = "info"
+
+# Log format: json, text, pretty
+format = "pretty"
+
+# Log destination: stdout, file, both
+destination = "stdout"
+
+# =============================================================================
+# Neural Intelligence Settings
+# =============================================================================
+
+[neural]
+# Enable SONA (Self-Optimizing Neural Architecture)
+sona_enabled = true
+
+# Enable HNSW vector search
+hnsw_enabled = true
+
+# HNSW index parameters
+hnsw_m = 16
+hnsw_ef_construction = 200
+hnsw_ef_search = 100
+
+# Enable pattern learning
+pattern_learning = true
+
+# Learning rate for neural adaptation
+learning_rate = 0.01
+
+# =============================================================================
+# Swarm Orchestration Settings
+# =============================================================================
+
+[swarm]
+# Default topology: hierarchical, mesh, ring, star
+default_topology = "hierarchical"
+
+# Default strategy: balanced, specialized, adaptive
+default_strategy = "specialized"
+
+# Consensus algorithm: raft, byzantine, gossip
+consensus = "raft"
+
+# Enable anti-drift measures
+anti_drift = true
+
+# Checkpoint interval (tasks)
+checkpoint_interval = 10
+
+# =============================================================================
+# Hooks Configuration
+# =============================================================================
+
+[hooks]
+# Enable lifecycle hooks
+enabled = true
+
+# Pre-task hook
+pre_task = true
+
+# Post-task hook (for learning)
+post_task = true
+
+# Enable neural training on post-edit
+train_on_edit = true
+
+# =============================================================================
+# Background Workers
+# =============================================================================
+
+[workers]
+# Enable background workers
+enabled = true
+
+# Worker configuration
+[workers.audit]
+enabled = true
+priority = "critical"
+interval = 300
+
+[workers.optimize]
+enabled = true
+priority = "high"
+interval = 600
+
+[workers.consolidate]
+enabled = true
+priority = "low"
+interval = 1800
diff --git a/.agents/skills/memory-management/SKILL.md b/.agents/skills/memory-management/SKILL.md
new file mode 100644
index 0000000..c337ff9
--- /dev/null
+++ b/.agents/skills/memory-management/SKILL.md
@@ -0,0 +1,126 @@
+---
+name: memory-management
+description: >
+ AgentDB memory system with HNSW vector search. Provides 150x-12,500x faster pattern retrieval, persistent storage, and semantic search capabilities for learning and knowledge management.
+ Use when: need to store successful patterns, searching for similar solutions, semantic lookup of past work, learning from previous tasks, sharing knowledge between agents, building knowledge base.
+ Skip when: no learning needed, ephemeral one-off tasks, external data sources available, read-only exploration.
+---
+
+# Memory Management Skill
+
+## Purpose
+AgentDB memory system with HNSW vector search. Provides 150x-12,500x faster pattern retrieval, persistent storage, and semantic search capabilities for learning and knowledge management.
+
+## When to Trigger
+- need to store successful patterns
+- searching for similar solutions
+- semantic lookup of past work
+- learning from previous tasks
+- sharing knowledge between agents
+- building knowledge base
+
+## When to Skip
+- no learning needed
+- ephemeral one-off tasks
+- external data sources available
+- read-only exploration
+
+## Commands
+
+### Store Pattern
+Store a pattern or knowledge item in memory
+
+```bash
+npx @claude-flow/cli memory store --key "[key]" --value "[value]" --namespace patterns
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli memory store --key "auth-jwt-pattern" --value "JWT validation with refresh tokens" --namespace patterns
+```
+
+### Semantic Search
+Search memory using semantic similarity
+
+```bash
+npx @claude-flow/cli memory search --query "[search terms]" --limit 10
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli memory search --query "authentication best practices" --limit 5
+```
+
+### Retrieve Entry
+Retrieve a specific memory entry by key
+
+```bash
+npx @claude-flow/cli memory get --key "[key]" --namespace [namespace]
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli memory get --key "auth-jwt-pattern" --namespace patterns
+```
+
+### List Entries
+List all entries in a namespace
+
+```bash
+npx @claude-flow/cli memory list --namespace [namespace]
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli memory list --namespace patterns --limit 20
+```
+
+### Delete Entry
+Delete a memory entry
+
+```bash
+npx @claude-flow/cli memory delete --key "[key]" --namespace [namespace]
+```
+
+### Initialize HNSW Index
+Initialize HNSW vector search index
+
+```bash
+npx @claude-flow/cli memory init --enable-hnsw
+```
+
+### Memory Stats
+Show memory usage statistics
+
+```bash
+npx @claude-flow/cli memory stats
+```
+
+### Export Memory
+Export memory to JSON
+
+```bash
+npx @claude-flow/cli memory export --output memory-backup.json
+```
+
+
+## Scripts
+
+| Script | Path | Description |
+|--------|------|-------------|
+| `memory-backup` | `.agents/scripts/memory-backup.sh` | Backup memory to external storage |
+| `memory-consolidate` | `.agents/scripts/memory-consolidate.sh` | Consolidate and optimize memory |
+
+
+## References
+
+| Document | Path | Description |
+|----------|------|-------------|
+| `HNSW Guide` | `docs/hnsw.md` | HNSW vector search configuration |
+| `Memory Schema` | `docs/memory-schema.md` | Memory namespace and schema reference |
+
+## Best Practices
+1. Check memory for existing patterns before starting
+2. Use hierarchical topology for coordination
+3. Store successful patterns after completion
+4. Document any new learnings
diff --git a/.agents/skills/memory-management/scripts/memory-backup.sh b/.agents/skills/memory-management/scripts/memory-backup.sh
new file mode 100644
index 0000000..de09ebc
--- /dev/null
+++ b/.agents/skills/memory-management/scripts/memory-backup.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# Memory Management - Backup Script
+# Export memory to backup file
+
+set -e
+
+BACKUP_DIR="${BACKUP_DIR:-./.backups}"
+TIMESTAMP=$(date +%Y%m%d_%H%M%S)
+BACKUP_FILE="${BACKUP_DIR}/memory_${TIMESTAMP}.json"
+
+mkdir -p "$BACKUP_DIR"
+
+echo "Backing up memory to $BACKUP_FILE..."
+npx @claude-flow/cli memory export --output "$BACKUP_FILE"
+
+echo "Backup complete: $BACKUP_FILE"
diff --git a/.agents/skills/memory-management/scripts/memory-consolidate.sh b/.agents/skills/memory-management/scripts/memory-consolidate.sh
new file mode 100644
index 0000000..c0b76d8
--- /dev/null
+++ b/.agents/skills/memory-management/scripts/memory-consolidate.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# Memory Management - Consolidate Script
+# Optimize and consolidate memory
+
+set -e
+
+echo "Running memory consolidation..."
+npx @claude-flow/cli hooks worker dispatch --trigger consolidate
+
+echo "Memory consolidation complete"
+npx @claude-flow/cli memory stats
diff --git a/.agents/skills/security-audit/SKILL.md b/.agents/skills/security-audit/SKILL.md
new file mode 100644
index 0000000..83f7d64
--- /dev/null
+++ b/.agents/skills/security-audit/SKILL.md
@@ -0,0 +1,135 @@
+---
+name: security-audit
+description: >
+ Comprehensive security scanning and vulnerability detection. Includes input validation, path traversal prevention, CVE detection, and secure coding pattern enforcement.
+ Use when: authentication implementation, authorization logic, payment processing, user data handling, API endpoint creation, file upload handling, database queries, external API integration.
+ Skip when: read-only operations on public data, internal development tooling, static documentation, styling changes.
+---
+
+# Security Audit Skill
+
+## Purpose
+Comprehensive security scanning and vulnerability detection. Includes input validation, path traversal prevention, CVE detection, and secure coding pattern enforcement.
+
+## When to Trigger
+- authentication implementation
+- authorization logic
+- payment processing
+- user data handling
+- API endpoint creation
+- file upload handling
+- database queries
+- external API integration
+
+## When to Skip
+- read-only operations on public data
+- internal development tooling
+- static documentation
+- styling changes
+
+## Commands
+
+### Full Security Scan
+Run comprehensive security analysis on the codebase
+
+```bash
+npx @claude-flow/cli security scan --depth full
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli security scan --depth full --output security-report.json
+```
+
+### Input Validation Check
+Check for input validation issues
+
+```bash
+npx @claude-flow/cli security scan --check input-validation
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli security scan --check input-validation --path ./src/api
+```
+
+### Path Traversal Check
+Check for path traversal vulnerabilities
+
+```bash
+npx @claude-flow/cli security scan --check path-traversal
+```
+
+### SQL Injection Check
+Check for SQL injection vulnerabilities
+
+```bash
+npx @claude-flow/cli security scan --check sql-injection
+```
+
+### XSS Check
+Check for cross-site scripting vulnerabilities
+
+```bash
+npx @claude-flow/cli security scan --check xss
+```
+
+### CVE Scan
+Scan dependencies for known CVEs
+
+```bash
+npx @claude-flow/cli security cve --scan
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli security cve --scan --severity high
+```
+
+### Security Audit Report
+Generate full security audit report
+
+```bash
+npx @claude-flow/cli security audit --report
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli security audit --report --format markdown --output SECURITY.md
+```
+
+### Threat Modeling
+Run threat modeling analysis
+
+```bash
+npx @claude-flow/cli security threats --analyze
+```
+
+### Validate Secrets
+Check for hardcoded secrets
+
+```bash
+npx @claude-flow/cli security validate --check secrets
+```
+
+
+## Scripts
+
+| Script | Path | Description |
+|--------|------|-------------|
+| `security-scan` | `.agents/scripts/security-scan.sh` | Run full security scan pipeline |
+| `cve-remediate` | `.agents/scripts/cve-remediate.sh` | Auto-remediate known CVEs |
+
+
+## References
+
+| Document | Path | Description |
+|----------|------|-------------|
+| `Security Checklist` | `docs/security-checklist.md` | Security review checklist |
+| `OWASP Guide` | `docs/owasp-top10.md` | OWASP Top 10 mitigation guide |
+
+## Best Practices
+1. Check memory for existing patterns before starting
+2. Use hierarchical topology for coordination
+3. Store successful patterns after completion
+4. Document any new learnings
diff --git a/.agents/skills/security-audit/scripts/cve-remediate.sh b/.agents/skills/security-audit/scripts/cve-remediate.sh
new file mode 100644
index 0000000..60b8dea
--- /dev/null
+++ b/.agents/skills/security-audit/scripts/cve-remediate.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# Security Audit - CVE Remediation Script
+# Auto-remediate known CVEs
+
+set -e
+
+echo "Scanning for CVEs..."
+npx @claude-flow/cli security cve --scan --severity high
+
+echo "Attempting auto-remediation..."
+npm audit fix
+
+echo "Re-scanning after remediation..."
+npx @claude-flow/cli security cve --scan
+
+echo "CVE remediation complete"
diff --git a/.agents/skills/security-audit/scripts/security-scan.sh b/.agents/skills/security-audit/scripts/security-scan.sh
new file mode 100644
index 0000000..2601db1
--- /dev/null
+++ b/.agents/skills/security-audit/scripts/security-scan.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# Security Audit - Full Scan Script
+# Run comprehensive security scan pipeline
+
+set -e
+
+echo "Running full security scan..."
+
+# Input validation
+echo "Checking input validation..."
+npx @claude-flow/cli security scan --check input-validation
+
+# Path traversal
+echo "Checking path traversal..."
+npx @claude-flow/cli security scan --check path-traversal
+
+# SQL injection
+echo "Checking SQL injection..."
+npx @claude-flow/cli security scan --check sql-injection
+
+# XSS
+echo "Checking XSS..."
+npx @claude-flow/cli security scan --check xss
+
+# Secrets
+echo "Checking for hardcoded secrets..."
+npx @claude-flow/cli security validate --check secrets
+
+# CVE scan
+echo "Scanning dependencies for CVEs..."
+npx @claude-flow/cli security cve --scan
+
+echo "Security scan complete"
diff --git a/.agents/skills/sparc-methodology/SKILL.md b/.agents/skills/sparc-methodology/SKILL.md
new file mode 100644
index 0000000..d48e6ef
--- /dev/null
+++ b/.agents/skills/sparc-methodology/SKILL.md
@@ -0,0 +1,118 @@
+---
+name: sparc-methodology
+description: >
+ SPARC development workflow: Specification, Pseudocode, Architecture, Refinement, Completion. A structured approach for complex implementations that ensures thorough planning before coding.
+ Use when: new feature implementation, complex implementations, architectural changes, system redesign, integration work, unclear requirements.
+ Skip when: simple bug fixes, documentation updates, configuration changes, well-defined small tasks, routine maintenance.
+---
+
+# Sparc Methodology Skill
+
+## Purpose
+SPARC development workflow: Specification, Pseudocode, Architecture, Refinement, Completion. A structured approach for complex implementations that ensures thorough planning before coding.
+
+## When to Trigger
+- new feature implementation
+- complex implementations
+- architectural changes
+- system redesign
+- integration work
+- unclear requirements
+
+## When to Skip
+- simple bug fixes
+- documentation updates
+- configuration changes
+- well-defined small tasks
+- routine maintenance
+
+## Commands
+
+### Specification Phase
+Define requirements, acceptance criteria, and constraints
+
+```bash
+npx @claude-flow/cli hooks route --task "specification: [requirements]"
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli hooks route --task "specification: user authentication with OAuth2, MFA, and session management"
+```
+
+### Pseudocode Phase
+Write high-level pseudocode for the implementation
+
+```bash
+npx @claude-flow/cli hooks route --task "pseudocode: [feature]"
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli hooks route --task "pseudocode: OAuth2 login flow with token refresh"
+```
+
+### Architecture Phase
+Design system structure, interfaces, and dependencies
+
+```bash
+npx @claude-flow/cli hooks route --task "architecture: [design]"
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli hooks route --task "architecture: auth module with service layer, repository, and API endpoints"
+```
+
+### Refinement Phase
+Iterate on the design based on feedback
+
+```bash
+npx @claude-flow/cli hooks route --task "refinement: [feedback]"
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli hooks route --task "refinement: add rate limiting and brute force protection"
+```
+
+### Completion Phase
+Finalize implementation with tests and documentation
+
+```bash
+npx @claude-flow/cli hooks route --task "completion: [final checks]"
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli hooks route --task "completion: verify all tests pass, update API docs, security review"
+```
+
+### SPARC Coordinator
+Spawn SPARC coordinator agent
+
+```bash
+npx @claude-flow/cli agent spawn --type sparc-coord --name sparc-lead
+```
+
+
+## Scripts
+
+| Script | Path | Description |
+|--------|------|-------------|
+| `sparc-init` | `.agents/scripts/sparc-init.sh` | Initialize SPARC workflow for a new feature |
+| `sparc-review` | `.agents/scripts/sparc-review.sh` | Run SPARC phase review checklist |
+
+
+## References
+
+| Document | Path | Description |
+|----------|------|-------------|
+| `SPARC Overview` | `docs/sparc.md` | Complete SPARC methodology guide |
+| `Phase Templates` | `docs/sparc-templates.md` | Templates for each SPARC phase |
+
+## Best Practices
+1. Check memory for existing patterns before starting
+2. Use hierarchical topology for coordination
+3. Store successful patterns after completion
+4. Document any new learnings
diff --git a/.agents/skills/sparc-methodology/scripts/sparc-init.sh b/.agents/skills/sparc-methodology/scripts/sparc-init.sh
new file mode 100644
index 0000000..c861d92
--- /dev/null
+++ b/.agents/skills/sparc-methodology/scripts/sparc-init.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# SPARC Methodology - Init Script
+# Initialize SPARC workflow for a new feature
+
+set -e
+
+FEATURE_NAME="${1:-new-feature}"
+
+echo "Initializing SPARC workflow for: $FEATURE_NAME"
+
+# Create SPARC documentation directory
+mkdir -p "./docs/sparc/$FEATURE_NAME"
+
+# Create phase files
+touch "./docs/sparc/$FEATURE_NAME/1-specification.md"
+touch "./docs/sparc/$FEATURE_NAME/2-pseudocode.md"
+touch "./docs/sparc/$FEATURE_NAME/3-architecture.md"
+touch "./docs/sparc/$FEATURE_NAME/4-refinement.md"
+touch "./docs/sparc/$FEATURE_NAME/5-completion.md"
+
+echo "SPARC workflow initialized in ./docs/sparc/$FEATURE_NAME"
diff --git a/.agents/skills/sparc-methodology/scripts/sparc-review.sh b/.agents/skills/sparc-methodology/scripts/sparc-review.sh
new file mode 100644
index 0000000..f268d9e
--- /dev/null
+++ b/.agents/skills/sparc-methodology/scripts/sparc-review.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# SPARC Methodology - Review Script
+# Run SPARC phase review checklist
+
+set -e
+
+FEATURE_DIR="${1:-.}"
+
+echo "SPARC Phase Review Checklist"
+echo "============================="
+
+for phase in specification pseudocode architecture refinement completion; do
+ if [ -f "$FEATURE_DIR/${phase}.md" ]; then
+ echo "[x] $phase - found"
+ else
+ echo "[ ] $phase - missing"
+ fi
+done
diff --git a/.agents/skills/swarm-orchestration/SKILL.md b/.agents/skills/swarm-orchestration/SKILL.md
new file mode 100644
index 0000000..1e2a9df
--- /dev/null
+++ b/.agents/skills/swarm-orchestration/SKILL.md
@@ -0,0 +1,114 @@
+---
+name: swarm-orchestration
+description: >
+ Multi-agent swarm coordination for complex tasks. Uses hierarchical topology with specialized agents to break down and execute complex work across multiple files and modules.
+ Use when: 3+ files need changes, new feature implementation, cross-module refactoring, API changes with tests, security-related changes, performance optimization across codebase, database schema changes.
+ Skip when: single file edits, simple bug fixes (1-2 lines), documentation updates, configuration changes, quick exploration.
+---
+
+# Swarm Orchestration Skill
+
+## Purpose
+Multi-agent swarm coordination for complex tasks. Uses hierarchical topology with specialized agents to break down and execute complex work across multiple files and modules.
+
+## When to Trigger
+- 3+ files need changes
+- new feature implementation
+- cross-module refactoring
+- API changes with tests
+- security-related changes
+- performance optimization across codebase
+- database schema changes
+
+## When to Skip
+- single file edits
+- simple bug fixes (1-2 lines)
+- documentation updates
+- configuration changes
+- quick exploration
+
+## Commands
+
+### Initialize Swarm
+Start a new swarm with hierarchical topology (anti-drift)
+
+```bash
+npx @claude-flow/cli swarm init --topology hierarchical --max-agents 8 --strategy specialized
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli swarm init --topology hierarchical --max-agents 6 --strategy specialized
+```
+
+### Route Task
+Route a task to the appropriate agents based on task type
+
+```bash
+npx @claude-flow/cli hooks route --task "[task description]"
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli hooks route --task "implement OAuth2 authentication flow"
+```
+
+### Spawn Agent
+Spawn a specific agent type
+
+```bash
+npx @claude-flow/cli agent spawn --type [type] --name [name]
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli agent spawn --type coder --name impl-auth
+```
+
+### Monitor Status
+Check the current swarm status
+
+```bash
+npx @claude-flow/cli swarm status --verbose
+```
+
+### Orchestrate Task
+Orchestrate a task across multiple agents
+
+```bash
+npx @claude-flow/cli task orchestrate --task "[task]" --strategy adaptive
+```
+
+**Example:**
+```bash
+npx @claude-flow/cli task orchestrate --task "refactor auth module" --strategy parallel --max-agents 4
+```
+
+### List Agents
+List all active agents
+
+```bash
+npx @claude-flow/cli agent list --filter active
+```
+
+
+## Scripts
+
+| Script | Path | Description |
+|--------|------|-------------|
+| `swarm-start` | `.agents/scripts/swarm-start.sh` | Initialize swarm with default settings |
+| `swarm-monitor` | `.agents/scripts/swarm-monitor.sh` | Real-time swarm monitoring dashboard |
+
+
+## References
+
+| Document | Path | Description |
+|----------|------|-------------|
+| `Agent Types` | `docs/agents.md` | Complete list of agent types and capabilities |
+| `Topology Guide` | `docs/topology.md` | Swarm topology configuration guide |
+
+## Best Practices
+1. Check memory for existing patterns before starting
+2. Use hierarchical topology for coordination
+3. Store successful patterns after completion
+4. Document any new learnings
diff --git a/.agents/skills/swarm-orchestration/scripts/swarm-monitor.sh b/.agents/skills/swarm-orchestration/scripts/swarm-monitor.sh
new file mode 100644
index 0000000..5af1014
--- /dev/null
+++ b/.agents/skills/swarm-orchestration/scripts/swarm-monitor.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+# Swarm Orchestration - Monitor Script
+# Real-time swarm monitoring
+
+set -e
+
+echo "Starting swarm monitor..."
+npx @claude-flow/cli swarm status --watch --interval 5
diff --git a/.agents/skills/swarm-orchestration/scripts/swarm-start.sh b/.agents/skills/swarm-orchestration/scripts/swarm-start.sh
new file mode 100644
index 0000000..6755acc
--- /dev/null
+++ b/.agents/skills/swarm-orchestration/scripts/swarm-start.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Swarm Orchestration - Start Script
+# Initialize swarm with default anti-drift settings
+
+set -e
+
+echo "Initializing hierarchical swarm..."
+npx @claude-flow/cli swarm init \
+ --topology hierarchical \
+ --max-agents 8 \
+ --strategy specialized
+
+echo "Swarm initialized successfully"
+npx @claude-flow/cli swarm status
diff --git a/.claude-flow/tasks/store.json b/.claude-flow/tasks/store.json
new file mode 100644
index 0000000..0b3075d
--- /dev/null
+++ b/.claude-flow/tasks/store.json
@@ -0,0 +1,144 @@
+{
+ "tasks": {
+ "task-1773164482180-yqy5i7": {
+ "taskId": "task-1773164482180-yqy5i7",
+ "type": "feature",
+ "description": "Add PkgID field to OrderRemark struct and parse pkg_id:XX in remark.Parse()",
+ "priority": "high",
+ "status": "completed",
+ "progress": 100,
+ "assignedTo": [],
+ "tags": [
+ "remark",
+ "parsing",
+ "ichiban"
+ ],
+ "createdAt": "2026-03-10T17:41:22.180Z",
+ "startedAt": null,
+ "completedAt": "2026-03-10T17:41:55.018Z",
+ "result": {
+ "reason": "Added PkgID field to OrderRemark struct and pkg_id: parsing branch in Parse()"
+ }
+ },
+ "task-1773164482201-s9jemx": {
+ "taskId": "task-1773164482201-s9jemx",
+ "type": "feature",
+ "description": "Extend calcPaidByPriceDraw with three-way classification: Case1 ActivityID>0 (lottery), Case2 IssueID>0 (matching game via activity_issues), Case3 PkgID>0 (ichiban via game_pass_packages)",
+ "priority": "high",
+ "status": "completed",
+ "progress": 100,
+ "assignedTo": [],
+ "tags": [
+ "channel-stats",
+ "matching-game",
+ "ichiban",
+ "calcPaidByPriceDraw"
+ ],
+ "createdAt": "2026-03-10T17:41:22.201Z",
+ "startedAt": null,
+ "completedAt": "2026-03-10T17:42:34.567Z",
+ "result": {
+ "reason": "Extended calcPaidByPriceDraw with three-way classification: lottery (ActivityID), matching game (IssueID→activity_issues→activities), ichiban (PkgID→game_pass_packages)"
+ }
+ },
+ "task-1773164482206-mhmqsb": {
+ "taskId": "task-1773164482206-mhmqsb",
+ "type": "feature",
+ "description": "Build verification: run make build-mac to ensure compilation passes after changes",
+ "priority": "normal",
+ "status": "completed",
+ "progress": 100,
+ "assignedTo": [],
+ "tags": [
+ "build",
+ "verification"
+ ],
+ "createdAt": "2026-03-10T17:41:22.206Z",
+ "startedAt": null,
+ "completedAt": "2026-03-10T17:43:27.419Z",
+ "result": {
+ "reason": "Build passed successfully on macOS"
+ }
+ },
+ "task-1773166041411-fmshox": {
+ "taskId": "task-1773166041411-fmshox",
+ "type": "feature",
+ "description": "Extend StatsOverview and StatsDailyItem structs with cost_cents, profit_cents, total_cost, total_profit fields",
+ "priority": "high",
+ "status": "completed",
+ "progress": 100,
+ "assignedTo": [],
+ "tags": [
+ "channel-stats",
+ "profit-loss",
+ "structs"
+ ],
+ "createdAt": "2026-03-10T18:07:21.411Z",
+ "startedAt": null,
+ "completedAt": "2026-03-10T18:07:47.297Z",
+ "result": {
+ "reason": "Extended StatsOverview with TotalCostCents/TotalProfitCents/TotalCost/TotalProfit and StatsDailyItem with CostCents/ProfitCents"
+ }
+ },
+ "task-1773166041417-di6rsd": {
+ "taskId": "task-1773166041417-di6rsd",
+ "type": "feature",
+ "description": "Implement calcCostByInventory helper function: query user_inventory with item card multiplier, grouped by date",
+ "priority": "high",
+ "status": "completed",
+ "progress": 100,
+ "assignedTo": [],
+ "tags": [
+ "channel-stats",
+ "profit-loss",
+ "cost-calculation"
+ ],
+ "createdAt": "2026-03-10T18:07:21.417Z",
+ "startedAt": null,
+ "completedAt": "2026-03-10T18:08:23.196Z",
+ "result": {
+ "reason": "Implemented calcCostByInventory with 6-table JOIN chain, item card multiplier, COALESCE fallback, and optional date range"
+ }
+ },
+ "task-1773166041422-efwp8w": {
+ "taskId": "task-1773166041422-efwp8w",
+ "type": "feature",
+ "description": "Integrate calcCostByInventory into GetStats: Overview all-time cost + daily trend cost/profit",
+ "priority": "high",
+ "status": "completed",
+ "progress": 100,
+ "assignedTo": [],
+ "tags": [
+ "channel-stats",
+ "profit-loss",
+ "integration"
+ ],
+ "createdAt": "2026-03-10T18:07:21.422Z",
+ "startedAt": null,
+ "completedAt": "2026-03-10T18:09:08.231Z",
+ "result": {
+ "reason": "Integrated calcCostByInventory into GetStats: Overview all-time cost/profit + daily trend cost/profit"
+ }
+ },
+ "task-1773166041428-fwp50t": {
+ "taskId": "task-1773166041428-fwp50t",
+ "type": "feature",
+ "description": "Build verification and integration test against dev_game database",
+ "priority": "normal",
+ "status": "completed",
+ "progress": 100,
+ "assignedTo": [],
+ "tags": [
+ "build",
+ "verification"
+ ],
+ "createdAt": "2026-03-10T18:07:21.428Z",
+ "startedAt": null,
+ "completedAt": "2026-03-10T18:10:06.759Z",
+ "result": {
+ "reason": "Build passed. Integration test shows: 754 inventory records, 2 with double card (双倍快乐水 ×2.0), cost=5100.50元, revenue(actual_amount)=545.00元"
+ }
+ }
+ },
+ "version": "3.0.0"
+}
\ No newline at end of file
diff --git a/.claude/plan/channel-stats-frontend.md b/.claude/plan/channel-stats-frontend.md
new file mode 100644
index 0000000..d1a5f54
--- /dev/null
+++ b/.claude/plan/channel-stats-frontend.md
@@ -0,0 +1,249 @@
+# 渠道统计 — 前端盈亏展示
+
+## 📋 实施计划:渠道统计页面新增成本/盈亏展示
+
+### 任务类型
+- [x] 前端
+- [ ] 后端
+- [ ] 全栈
+
+### 需求概述
+
+后端 `/admin/channels/:id/stats` 接口已新增以下字段:
+
+**Overview 新增**:
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `total_cost_cents` | number | 总成本(分) |
+| `total_profit_cents` | number | 盈亏(分) = paid - cost |
+| `total_cost` | number | 总成本(元) |
+| `total_profit` | number | 盈亏(元) |
+
+**趋势图每日新增**:
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `cost_cents` | number | 当日成本(分) |
+| `profit_cents` | number | 当日盈亏(分) |
+
+### 技术方案
+
+#### UI 设计
+
+**Overview 区域**:
+- 现有 3 个卡片(用户、订单、实付金额)→ 扩展为 **5 个卡片**
+- 新增:**总成本** 卡片 + **盈亏** 卡片
+- 布局:从 `grid-cols-3` 改为 `grid-cols-5`(或在移动端自适应 `grid-cols-2 md:grid-cols-5`)
+- 盈亏卡片需根据正/负值显示不同颜色(盈利=绿色,亏损=红色)
+
+**趋势图区域**:
+- 现有 2 个 Tab(用户增长、付费数据)→ 新增第 3 个 Tab:**盈亏分析**
+- 盈亏分析 Tab 包含 3 条曲线:实付金额、成本、盈亏
+- 盈亏曲线可使用虚线区分
+
+### 实施步骤
+
+#### Step 1: 更新 TypeScript 类型定义
+
+**文件**:`web/admin/src/api/channels.ts`
+
+在 `StatsOverview` 接口新增:
+```typescript
+export interface StatsOverview {
+ total_users: number
+ total_orders: number
+ total_gmv: number
+ total_paid_cents?: number
+ // 新增
+ total_cost_cents?: number // 总成本(分)
+ total_profit_cents?: number // 盈亏(分)
+ total_cost?: number // 总成本(元)
+ total_profit?: number // 盈亏(元)
+}
+```
+
+在 `StatsDailyItem` 接口新增:
+```typescript
+export interface StatsDailyItem {
+ date: string
+ user_count: number
+ order_count: number
+ gmv: number
+ paid_cents?: number
+ // 新增
+ cost_cents?: number // 当日成本(分)
+ profit_cents?: number // 当日盈亏(分)
+}
+```
+
+#### Step 2: 更新 Overview 卡片区域
+
+**文件**:`web/admin/src/views/operations/channels/index.vue`
+
+**2.1** 布局从 `grid-cols-3` 改为 `grid-cols-5`
+
+**2.2** 新增两个 `ArtStatsCard`:
+
+```vue
+
+
+
+
+
+```
+
+**2.3** 新增 computed 属性:
+
+```typescript
+const totalCostYuan = computed(() => {
+ const cents = statsData.value.overview.total_cost_cents
+ if (typeof cents === 'number') {
+ return Number((cents / 100).toFixed(2))
+ }
+ return 0
+})
+
+const totalProfitYuan = computed(() => {
+ const cents = statsData.value.overview.total_profit_cents
+ if (typeof cents === 'number') {
+ return Number((cents / 100).toFixed(2))
+ }
+ return 0
+})
+
+const profitCardStyle = computed(() =>
+ totalProfitYuan.value >= 0 ? 'bg-green-50' : 'bg-red-50'
+)
+
+const profitTextColor = computed(() =>
+ totalProfitYuan.value >= 0 ? '#10B981' : '#EF4444'
+)
+
+const profitIconStyle = computed(() =>
+ totalProfitYuan.value >= 0 ? 'bg-green-500' : 'bg-red-500'
+)
+
+const profitDescription = computed(() =>
+ totalProfitYuan.value >= 0 ? '盈利' : '亏损'
+)
+```
+
+#### Step 3: 更新趋势图 Tab
+
+**文件**:`web/admin/src/views/operations/channels/index.vue`
+
+**3.1** 在 `el-radio-group` 新增 Tab:
+
+```vue
+
+ 用户增长
+ 付费数据
+ 盈亏分析
+
+```
+
+**3.2** 在 `chartData` computed 中新增 `profit` 分支:
+
+```typescript
+const chartData = computed(() => {
+ if (statsTab.value === 'growth') {
+ return [
+ { name: '新增用户', data: statsData.value.daily.map(i => i.user_count), smooth: true, color: '#409EFF' }
+ ]
+ } else if (statsTab.value === 'revenue') {
+ return [
+ { name: '订单数', data: statsData.value.daily.map(i => i.order_count), smooth: true, color: '#67C23A' },
+ { name: '实付金额', data: statsData.value.daily.map(i => getDailyPaidYuan(i)), smooth: true, color: '#E6A23C' }
+ ]
+ } else {
+ // profit tab
+ return [
+ { name: '实付(元)', data: statsData.value.daily.map(i => getDailyPaidYuan(i)), smooth: true, color: '#E6A23C' },
+ { name: '成本(元)', data: statsData.value.daily.map(i => getDailyCostYuan(i)), smooth: true, color: '#7C3AED' },
+ { name: '盈亏(元)', data: statsData.value.daily.map(i => getDailyProfitYuan(i)), smooth: true, color: '#10B981' }
+ ]
+ }
+})
+```
+
+**3.3** 新增辅助函数:
+
+```typescript
+function getDailyCostYuan(item: { cost_cents?: number }) {
+ if (typeof item.cost_cents === 'number') {
+ return Number((item.cost_cents / 100).toFixed(2))
+ }
+ return 0
+}
+
+function getDailyProfitYuan(item: { profit_cents?: number }) {
+ if (typeof item.profit_cents === 'number') {
+ return Number((item.profit_cents / 100).toFixed(2))
+ }
+ return 0
+}
+```
+
+#### Step 4: 更新 statsData 初始值
+
+**文件**:`web/admin/src/views/operations/channels/index.vue`
+
+```typescript
+const statsData = ref({
+ overview: {
+ total_users: 0, total_orders: 0, total_gmv: 0, total_paid_cents: 0,
+ total_cost_cents: 0, total_profit_cents: 0, total_cost: 0, total_profit: 0
+ },
+ daily: []
+})
+```
+
+### 关键文件
+
+| 文件 | 操作 | 说明 |
+|------|------|------|
+| `web/admin/src/api/channels.ts:L68-86` | 修改 | 扩展 StatsOverview 和 StatsDailyItem 接口 |
+| `web/admin/src/views/operations/channels/index.vue:L155-184` | 修改 | Overview 卡片区域新增成本/盈亏卡 |
+| `web/admin/src/views/operations/channels/index.vue:L202-205` | 修改 | 趋势图新增盈亏分析 Tab |
+| `web/admin/src/views/operations/channels/index.vue:L482-558` | 修改 | 新增 computed 属性和辅助函数 |
+
+### 风险与缓解
+
+| 风险 | 严重程度 | 缓解措施 |
+|------|---------|----------|
+| 5列卡片在窄屏溢出 | 低 | 使用响应式 `grid-cols-2 md:grid-cols-5`,必要时改为 `grid-cols-3` + 第二行 `grid-cols-2` |
+| 后端字段为空(旧数据) | 已解决 | 所有新字段使用 `?` 可选,computed 中做 `typeof` 检查,默认 0 |
+| ArtStatsCard 不支持负数展示 | 低 | ArtCountTo 组件底层支持负数(基于 countUp.js),无需额外处理 |
+| 盈亏曲线可能有负值 | 低 | ECharts 原生支持负值 Y 轴,图表会自动适配 |
+
+### 验收标准
+
+- [ ] TypeScript 类型定义包含新字段
+- [ ] Overview 展示 5 个卡片(用户、订单、实付、成本、盈亏)
+- [ ] 盈亏卡片根据正/负值动态切换颜色(绿/红)
+- [ ] 趋势图新增"盈亏分析"Tab
+- [ ] 盈亏分析 Tab 展示 3 条曲线(实付、成本、盈亏)
+- [ ] `pnpm build` 编译通过
+- [ ] `pnpm type-check` 类型检查通过
+
+### SESSION_ID(供 /ccg:execute 使用)
+
+- CODEX_SESSION: N/A
+- GEMINI_SESSION: N/A
diff --git a/.claude/plan/channel-stats-optimization.md b/.claude/plan/channel-stats-optimization.md
new file mode 100644
index 0000000..b4bc1ca
--- /dev/null
+++ b/.claude/plan/channel-stats-optimization.md
@@ -0,0 +1,311 @@
+# 渠道统计接口优化计划
+
+## 需求概述
+
+优化 `/admin/channels/:channel_id/stats` 接口:
+
+| 指标 | 当前实现 | 优化后 |
+|------|---------|--------|
+| 累计用户 | `COUNT(users WHERE channel_id = X)` | 保持不变 — **全量统计,不限时间** |
+| 累计订单 | `COUNT(orders JOIN users ...)` | 保持不变 — **全量统计,不限时间** |
+| 累计实付金额 | `SUM(orders.actual_amount)` | remark → activityID → `activities.price_draw × count` — **全量统计,不限时间** |
+| 趋势图表 | 按**月**分组(`days` 参数实际当月用) | 修正为按**天**分组,`days` 参数控制天数范围 |
+
+## 确认的决策
+
+- ✅ 直接用 remark 中 activityID 查 `activities.price_draw`
+- ✅ 软删除活动也计入(使用 `Unscoped`)
+- ✅ `days` 参数修正为按天计算
+- ✅ Overview 三个指标为全量(不受 days 限制)
+
+## 受影响的代码
+
+| 方法 | 文件 | 行号 | 改动内容 |
+|------|------|------|---------|
+| `GetStats` | `internal/service/channel/channel.go` | L238-355 | 核心改动:金额计算 + days 修正 + 按天分组 |
+| `List` | `internal/service/channel/channel.go` | L157-236 | 同步改动:列表 paid_amount 用 price_draw 计算 |
+| `StatsOutput` / `StatsDailyItem` | `internal/service/channel/channel.go` | L66-84 | 结构体不变,`Daily` 改为按天粒度 |
+
+## 实施步骤
+
+### Step 1: 新增 `orderRemarkRow` 类型和 `calcPaidByPriceDraw` 辅助函数
+
+**文件**:`internal/service/channel/channel.go`
+
+```go
+type orderRemarkRow struct {
+ Remark string
+ CreatedAt time.Time
+}
+
+// calcPaidByPriceDraw 解析订单 remark 中的 activityID + count,
+// 批量查 activities.price_draw(含软删除),计算实付金额
+// 返回:总金额(分)、按日期key分组的金额
+func (s *service) calcPaidByPriceDraw(ctx context.Context, rows []orderRemarkRow, dateFmt string) (int64, map[string]int64, error) {
+ if len(rows) == 0 {
+ return 0, nil, nil
+ }
+
+ // 1. 解析 remark,收集 unique activityIDs
+ type parsed struct {
+ activityID int64
+ count int64
+ dateKey string
+ }
+ var items []parsed
+ idSet := make(map[int64]struct{})
+
+ for _, r := range rows {
+ rmk := remark.Parse(r.Remark)
+ if rmk.ActivityID > 0 {
+ items = append(items, parsed{
+ activityID: rmk.ActivityID,
+ count: rmk.Count,
+ dateKey: r.CreatedAt.Format(dateFmt),
+ })
+ idSet[rmk.ActivityID] = struct{}{}
+ }
+ }
+
+ // 2. 批量查 activities.price_draw(含软删除 Unscoped)
+ actIDs := make([]int64, 0, len(idSet))
+ for id := range idSet {
+ actIDs = append(actIDs, id)
+ }
+ priceMap := make(map[int64]int64)
+ if len(actIDs) > 0 {
+ var acts []model.Activities
+ s.readDB.Activities.WithContext(ctx).UnderlyingDB().
+ Unscoped().
+ Table("activities").
+ Select("id, price_draw").
+ Where("id IN ?", actIDs).
+ Find(&acts)
+ for _, a := range acts {
+ priceMap[a.ID] = a.PriceDraw
+ }
+ }
+
+ // 3. 计算
+ var total int64
+ byDate := make(map[string]int64)
+ for _, item := range items {
+ if price, ok := priceMap[item.activityID]; ok {
+ amt := price * item.count
+ total += amt
+ byDate[item.dateKey] += amt
+ }
+ }
+ return total, byDate, nil
+}
+```
+
+### Step 2: 重写 `GetStats` — 日期逻辑修正 + 金额计算
+
+**改动要点**:
+
+1. **参数 `days` 真正按天**:`startDate = now.AddDate(0, 0, -days+1)`
+2. **Overview 全量不限时间**:用户数、订单数、实付金额均查全量
+3. **趋势按天分组**:`DATE_FORMAT(..., '%Y-%m-%d')` 替代 `'%Y-%m'`
+4. **金额用 price_draw**:调用 `calcPaidByPriceDraw`
+
+```go
+func (s *service) GetStats(ctx context.Context, channelID int64, days int, startDateStr, endDateStr string) (*StatsOutput, error) {
+ now := time.Now()
+
+ // 校验渠道存在
+ _, err := s.readDB.Channels.WithContext(ctx).Where(s.readDB.Channels.ID.Eq(channelID)).First()
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return nil, ErrChannelNotFound
+ }
+ return nil, err
+ }
+
+ out := &StatsOutput{}
+
+ // ========== 1. Overview(全量,不限时间)==========
+
+ // 1a. 累计用户
+ userCount, _ := s.readDB.Users.WithContext(ctx).
+ Where(s.readDB.Users.ChannelID.Eq(channelID)).Count()
+ out.Overview.TotalUsers = userCount
+
+ // 1b. 累计订单数
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ type countResult struct{ Count int64 }
+ var cr countResult
+ s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("count(*) as count").
+ Where(orderFilter, channelID).
+ Scan(&cr)
+ out.Overview.TotalOrders = cr.Count
+
+ // 1c. 累计实付金额(全量订单 remark → price_draw × count)
+ var allRemarks []orderRemarkRow
+ s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.remark, orders.created_at").
+ Where(orderFilter, channelID).
+ Scan(&allRemarks)
+
+ totalPaid, _, _ := s.calcPaidByPriceDraw(ctx, allRemarks, "2006-01-02")
+ out.Overview.TotalPaidCents = totalPaid
+ out.Overview.TotalGMV = totalPaid / 100
+
+ // ========== 2. 趋势图(按天分组,受 days 限制)==========
+
+ // 2a. 计算日期范围
+ var startDate, endDate time.Time
+ if startDateStr != "" && endDateStr != "" {
+ startDate, _ = time.Parse("2006-01-02", startDateStr)
+ endDate, _ = time.Parse("2006-01-02", endDateStr)
+ endDate = endDate.Add(24*time.Hour - time.Second)
+ } else {
+ if days <= 0 {
+ days = 12
+ }
+ startDate = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).
+ AddDate(0, 0, -days+1)
+ endDate = now
+ }
+
+ // 2b. 初始化日期桶(每天一个)
+ dateMap := make(map[string]*StatsDailyItem)
+ var dateList []string
+ for d := startDate; !d.After(endDate); d = d.AddDate(0, 0, 1) {
+ key := d.Format("2006-01-02")
+ dateList = append(dateList, key)
+ dateMap[key] = &StatsDailyItem{Date: key}
+ }
+
+ // 2c. 每日新增用户
+ type dailyCount struct {
+ Date string
+ Count int64
+ }
+ var dailyUsers []dailyCount
+ s.readDB.Users.WithContext(ctx).UnderlyingDB().Table("users").
+ Select("DATE_FORMAT(created_at, '%Y-%m-%d') as date, count(*) as count").
+ Where("channel_id = ? AND deleted_at IS NULL AND created_at >= ? AND created_at <= ?",
+ channelID, startDate, endDate).
+ Group("date").Scan(&dailyUsers)
+ for _, u := range dailyUsers {
+ if item, ok := dateMap[u.Date]; ok {
+ item.UserCount = u.Count
+ }
+ }
+
+ // 2d. 每日订单数
+ var dailyOrders []dailyCount
+ s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("DATE_FORMAT(orders.created_at, '%Y-%m-%d') as date, count(*) as count").
+ Where(orderFilter+" AND orders.created_at >= ? AND orders.created_at <= ?",
+ channelID, startDate, endDate).
+ Group("date").Scan(&dailyOrders)
+ for _, o := range dailyOrders {
+ if item, ok := dateMap[o.Date]; ok {
+ item.OrderCount = o.Count
+ }
+ }
+
+ // 2e. 每日实付金额(remark → price_draw)
+ var rangeRemarks []orderRemarkRow
+ s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.remark, orders.created_at").
+ Where(orderFilter+" AND orders.created_at >= ? AND orders.created_at <= ?",
+ channelID, startDate, endDate).
+ Scan(&rangeRemarks)
+
+ _, dailyPaid, _ := s.calcPaidByPriceDraw(ctx, rangeRemarks, "2006-01-02")
+ for dateKey, paid := range dailyPaid {
+ if item, ok := dateMap[dateKey]; ok {
+ item.PaidCents = paid
+ item.GMV = paid / 100
+ }
+ }
+
+ // 2f. 组装输出
+ for _, d := range dateList {
+ out.Daily = append(out.Daily, *dateMap[d])
+ }
+
+ return out, nil
+}
+```
+
+### Step 3: 同步修改 `List` 方法的金额计算
+
+**文件**:`internal/service/channel/channel.go`,L206-223
+
+**当前**:`SUM(orders.actual_amount)` 聚合。
+
+**修改为**:按渠道查询所有订单 remark,分渠道调用 `calcPaidByPriceDraw`。
+
+```go
+// 替换原有 paidResults 查询逻辑:
+if len(channelIDs) > 0 {
+ // ... userCount 查询保持不变 ...
+
+ // 实付金额:查所有渠道的订单 remark
+ type remarkWithChannel struct {
+ ChannelID int64
+ Remark string
+ CreatedAt time.Time
+ }
+ var chRemarks []remarkWithChannel
+ s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("users.channel_id, orders.remark, orders.created_at").
+ Where("users.channel_id IN ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)", channelIDs).
+ Scan(&chRemarks)
+
+ // 按渠道分组
+ grouped := make(map[int64][]orderRemarkRow)
+ for _, r := range chRemarks {
+ grouped[r.ChannelID] = append(grouped[r.ChannelID], orderRemarkRow{
+ Remark: r.Remark, CreatedAt: r.CreatedAt,
+ })
+ }
+
+ for chID, rows := range grouped {
+ total, _, _ := s.calcPaidByPriceDraw(ctx, rows, "2006-01-02")
+ paidStats[chID] = total
+ }
+}
+```
+
+### Step 4: 添加 remark import
+
+确保文件顶部 import 包含:
+```go
+"bindbox-game/internal/pkg/util/remark"
+```
+
+## 风险与缓解
+
+| 风险 | 严重程度 | 缓解措施 |
+|------|---------|----------|
+| remark 格式不一致 | 中 | `remark.Parse()` 已处理 `activity:` 和 `lottery:activity:` 两种前缀 |
+| 软删除活动 | 已解决 | 使用 `Unscoped()` 查询,确保被删活动仍有 price_draw |
+| List 方法大量订单性能 | 中 | 单次查询所有渠道订单 remark,Go 中分组计算,比 N+1 高效 |
+| days 参数前端兼容 | 低 | 前端传 `days=12` 原意应为12天,修正后行为与参数名一致 |
+
+## 验收标准
+
+- [ ] Overview 累计用户:全量统计 `users.channel_id = X` 的用户数(不限时间)
+- [ ] Overview 累计订单:全量统计有效订单数(不限时间)
+- [ ] Overview 累计实付金额:全量基于 `activities.price_draw × count` 计算(包含软删除活动)
+- [ ] 趋势图按**天**分组,`days` 参数控制显示天数
+- [ ] 渠道列表页 `paid_amount` 同步使用 price_draw 计算
+- [ ] 编译通过 `make build-mac`
+- [ ] 现有功能无回归
+
+## SESSION_ID(供 /ccg:execute 使用)
+
+- CODEX_SESSION: N/A
+- GEMINI_SESSION: N/A
diff --git a/.claude/plan/channel-stats-profit-loss.md b/.claude/plan/channel-stats-profit-loss.md
new file mode 100644
index 0000000..53efaa5
--- /dev/null
+++ b/.claude/plan/channel-stats-profit-loss.md
@@ -0,0 +1,187 @@
+# 渠道统计 — 盈亏计算
+
+## 需求概述
+
+在 `/admin/channels/:id/stats` 接口的 Overview 和趋势图中新增盈亏指标。
+
+### 盈亏公式
+
+```
+盈亏 = 收入(price_draw × count) - 成本(奖品价值 × 道具卡倍数)
+```
+
+### 数据源
+
+| 维度 | 来源 | 说明 |
+|------|------|------|
+| **收入** | 已有 `calcPaidByPriceDraw` | 三路分类:抽奖/对对碰/一番赏 |
+| **成本** | `user_inventory.value_cents` | 奖品价值快照(分),fallback: `activity_reward_settings.price_snapshot_cents` → `products.price` |
+| **道具卡倍数** | `orders.item_card_id` → `user_item_cards.card_id` → `system_item_cards.reward_multiplier_x1000` | 双倍卡 = 2000(千分比),无卡 = 1000 |
+
+### 成本计算公式(参考已有 dashboard_activity.go:L234-239)
+
+```sql
+单件成本 = COALESCE(NULLIF(user_inventory.value_cents, 0),
+ activity_reward_settings.price_snapshot_cents,
+ products.price, 0)
+
+道具卡倍数 = GREATEST(COALESCE(system_item_cards.reward_multiplier_x1000, 1000), 1000) / 1000
+
+总成本 = SUM(单件成本 × 道具卡倍数)
+```
+
+## 实施步骤
+
+### Step 1: 扩展响应结构体
+
+**文件**:`internal/service/channel/channel.go`
+
+```go
+type StatsOverview struct {
+ TotalUsers int64 `json:"total_users"`
+ TotalOrders int64 `json:"total_orders"`
+ TotalGMV int64 `json:"total_gmv"`
+ TotalPaidCents int64 `json:"total_paid_cents"`
+ // 新增
+ TotalCostCents int64 `json:"total_cost_cents"` // 总成本(分)
+ TotalProfitCents int64 `json:"total_profit_cents"` // 盈亏(分) = paid - cost
+ TotalCost int64 `json:"total_cost"` // 总成本(元)
+ TotalProfit int64 `json:"total_profit"` // 盈亏(元)
+}
+
+type StatsDailyItem struct {
+ Date string `json:"date"`
+ UserCount int64 `json:"user_count"`
+ OrderCount int64 `json:"order_count"`
+ GMV int64 `json:"gmv"`
+ PaidCents int64 `json:"paid_cents"`
+ // 新增
+ CostCents int64 `json:"cost_cents"` // 当日成本(分)
+ ProfitCents int64 `json:"profit_cents"` // 当日盈亏(分)
+}
+```
+
+### Step 2: 新增 `calcCostByInventory` 辅助函数
+
+**文件**:`internal/service/channel/channel.go`
+
+**输入**:渠道用户 ID 列表 + 日期范围(可选)
+**输出**:总成本(分)、按日期分组的成本
+
+```go
+type costRow struct {
+ ValueCents int64
+ Multiplier int64 // reward_multiplier_x1000,无卡时=1000
+ CreatedAt time.Time
+}
+
+func (s *service) calcCostByInventory(ctx context.Context, channelID int64, dateFmt string, startDate, endDate *time.Time) (int64, map[string]int64) {
+ // SQL 核心逻辑(复用 dashboard_activity.go:L234-239 模式):
+ //
+ // SELECT
+ // COALESCE(NULLIF(ui.value_cents, 0), ars.price_snapshot_cents, p.price, 0) AS unit_cost,
+ // GREATEST(COALESCE(sic.reward_multiplier_x1000, 1000), 1000) AS multiplier,
+ // ui.created_at
+ // FROM user_inventory ui
+ // JOIN users u ON u.id = ui.user_id
+ // LEFT JOIN orders o ON o.id = ui.order_id
+ // LEFT JOIN activity_reward_settings ars ON ars.id = ui.reward_id
+ // LEFT JOIN products p ON p.id = ui.product_id
+ // LEFT JOIN user_item_cards uic ON uic.id = o.item_card_id
+ // LEFT JOIN system_item_cards sic ON sic.id = uic.card_id
+ // WHERE u.channel_id = ? AND u.deleted_at IS NULL
+ // AND ui.status IN (1, 3) -- 持有 or 已使用/发货
+ // AND COALESCE(ui.remark, '') NOT LIKE '%void%'
+ // AND (o.status = 2 OR ui.order_id = 0 OR ui.order_id IS NULL) -- 兼容历史
+ // [AND ui.created_at >= ? AND ui.created_at <= ?] -- 可选时间范围
+
+ // Go 侧计算:
+ // for each row:
+ // cost += unit_cost * multiplier / 1000
+ // byDate[dateKey] += unit_cost * multiplier / 1000
+}
+```
+
+**关键点**:
+- 通过 `users.channel_id` 过滤渠道用户
+- `ui.status IN (1, 3)`:只统计有效资产(持有 + 已发货),排除作废
+- `NOT LIKE '%void%'`:排除作废备注
+- `(o.status = 2 OR ui.order_id = 0 OR ui.order_id IS NULL)`:兼容历史数据
+- 道具卡倍数通过 `orders.item_card_id` → `user_item_cards.card_id` → `system_item_cards.reward_multiplier_x1000` 链路获取
+
+### Step 3: 在 `GetStats` 中调用成本计算
+
+**文件**:`internal/service/channel/channel.go`,`GetStats` 方法
+
+```go
+// ========== Overview 全量成本 ==========
+totalCost, _ := s.calcCostByInventory(ctx, channelID, "2006-01-02", nil, nil)
+out.Overview.TotalCostCents = totalCost
+out.Overview.TotalCost = totalCost / 100
+out.Overview.TotalProfitCents = out.Overview.TotalPaidCents - totalCost
+out.Overview.TotalProfit = out.Overview.TotalProfitCents / 100
+
+// ========== 趋势图日维度成本 ==========
+_, dailyCost := s.calcCostByInventory(ctx, channelID, "2006-01-02", &startDate, &endDate)
+for dateKey, cost := range dailyCost {
+ if item, ok := dateMap[dateKey]; ok {
+ item.CostCents = cost
+ item.ProfitCents = item.PaidCents - cost
+ }
+}
+```
+
+### Step 4: 在 `List` 中可选加入成本(列表页)
+
+**暂不实施**。列表页已有 `paid_amount`,盈亏是详情页指标,列表页展示所有渠道的成本查询开销较大。后续按需添加。
+
+## 关键文件
+
+| 文件 | 操作 | 说明 |
+|------|------|------|
+| `internal/service/channel/channel.go` | 修改 | 扩展结构体 + 新增 `calcCostByInventory` + 修改 `GetStats` |
+
+## 查询关系链
+
+```
+user_inventory
+ ├── JOIN users ON users.id = ui.user_id (过滤渠道)
+ ├── LEFT JOIN orders ON orders.id = ui.order_id (获取 item_card_id)
+ ├── LEFT JOIN activity_reward_settings ON ars.id = ui.reward_id (价格快照)
+ ├── LEFT JOIN products ON p.id = ui.product_id (商品价格 fallback)
+ ├── LEFT JOIN user_item_cards ON uic.id = o.item_card_id (道具卡实例)
+ └── LEFT JOIN system_item_cards ON sic.id = uic.card_id (道具卡倍数)
+```
+
+## 道具卡逻辑说明
+
+| 场景 | `reward_multiplier_x1000` | 效果 | 成本影响 |
+|------|---------------------------|------|---------|
+| 无道具卡 | NULL → COALESCE → 1000 | ×1.0 | 成本 = 奖品原价 |
+| 双倍卡 | 2000 | ×2.0 | 成本 = 奖品原价 × 2 |
+| 三倍卡(如有) | 3000 | ×3.0 | 成本 = 奖品原价 × 3 |
+
+**原理**:双倍卡让用户以相同支付价格获得双倍奖品,收入不变但成本翻倍,利润下降。
+
+## 风险与缓解
+
+| 风险 | 严重程度 | 缓解措施 |
+|------|---------|----------|
+| `user_inventory` 数据量大,全量查询慢 | 中 | 通过 `users.channel_id` 索引过滤,只查渠道用户 |
+| 历史资产无 `order_id` | 已解决 | `(o.status = 2 OR ui.order_id = 0 OR ui.order_id IS NULL)` 兼容 |
+| `value_cents = 0` 的历史数据 | 已解决 | COALESCE 链式 fallback 到 `price_snapshot_cents` → `products.price` |
+| 概率提升卡(EffectType=2)不影响成本 | 低 | `reward_multiplier_x1000` 只在 EffectType=1 时 > 1000,概率卡该字段为 1000,GREATEST 确保最小为 1.0 |
+
+## 验收标准
+
+- [ ] Overview 新增 `total_cost_cents`、`total_profit_cents`、`total_cost`、`total_profit`
+- [ ] 趋势图每天新增 `cost_cents`、`profit_cents`
+- [ ] 道具卡(双倍)正确计入成本(×2)
+- [ ] 无道具卡时成本不受影响(×1)
+- [ ] 成本计算排除 status=2(作废)和 void 备注的资产
+- [ ] 编译通过 `make build-mac`
+
+## SESSION_ID(供 /ccg:execute 使用)
+
+- CODEX_SESSION: N/A
+- GEMINI_SESSION: N/A
diff --git a/.gitignore b/.gitignore
index 52ae484..a417d65 100755
--- a/.gitignore
+++ b/.gitignore
@@ -36,3 +36,15 @@ configs/*.toml
.env
.env.*
!.env.example
+
+# Codex local configuration
+.codex/
+
+# Claude Flow runtime data
+.claude-flow/data/
+.claude-flow/logs/
+
+# Environment variables
+.env
+.env.local
+.env.*.local
diff --git a/.swarm/model-router-state.json b/.swarm/model-router-state.json
new file mode 100644
index 0000000..4d33d75
--- /dev/null
+++ b/.swarm/model-router-state.json
@@ -0,0 +1,14 @@
+{
+ "totalDecisions": 3,
+ "modelDistribution": {
+ "haiku": 0,
+ "sonnet": 0,
+ "opus": 3,
+ "inherit": 0
+ },
+ "avgComplexity": 0.42307874564459924,
+ "avgConfidence": 0.5675513529812717,
+ "circuitBreakerTrips": 0,
+ "lastUpdated": "2026-03-10T18:07:21.401Z",
+ "learningHistory": []
+}
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..48ea3ab
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,145 @@
+# bindbox_game
+
+> Multi-agent orchestration framework for agentic coding
+
+## Project Overview
+
+A Claude Flow powered project
+
+**Tech Stack**: TypeScript, Node.js
+**Architecture**: Domain-Driven Design with bounded contexts
+
+## Quick Start
+
+### Installation
+```bash
+npm install
+```
+
+### Build
+```bash
+npm run build
+```
+
+### Test
+```bash
+npm test
+```
+
+### Development
+```bash
+npm run dev
+```
+
+## Agent Coordination
+
+### Swarm Configuration
+
+This project uses hierarchical swarm coordination for complex tasks:
+
+| Setting | Value | Purpose |
+|---------|-------|---------|
+| Topology | `hierarchical` | Queen-led coordination (anti-drift) |
+| Max Agents | 8 | Optimal team size |
+| Strategy | `specialized` | Clear role boundaries |
+| Consensus | `raft` | Leader-based consistency |
+
+### When to Use Swarms
+
+**Invoke swarm for:**
+- Multi-file changes (3+ files)
+- New feature implementation
+- Cross-module refactoring
+- API changes with tests
+- Security-related changes
+- Performance optimization
+
+**Skip swarm for:**
+- Single file edits
+- Simple bug fixes (1-2 lines)
+- Documentation updates
+- Configuration changes
+
+### Available Skills
+
+Use `$skill-name` syntax to invoke:
+
+| Skill | Use Case |
+|-------|----------|
+| `$swarm-orchestration` | Multi-agent task coordination |
+| `$memory-management` | Pattern storage and retrieval |
+| `$sparc-methodology` | Structured development workflow |
+| `$security-audit` | Security scanning and CVE detection |
+
+### Agent Types
+
+| Type | Role | Use Case |
+|------|------|----------|
+| `researcher` | Requirements analysis | Understanding scope |
+| `architect` | System design | Planning structure |
+| `coder` | Implementation | Writing code |
+| `tester` | Test creation | Quality assurance |
+| `reviewer` | Code review | Security and quality |
+
+## Code Standards
+
+### File Organization
+- **NEVER** save to root folder
+- `/src` - Source code files
+- `/tests` - Test files
+- `/docs` - Documentation
+- `/config` - Configuration files
+
+### Quality Rules
+- Files under 500 lines
+- No hardcoded secrets
+- Input validation at boundaries
+- Typed interfaces for public APIs
+- TDD London School (mock-first) preferred
+
+### Commit Messages
+```
+():
+
+[optional body]
+
+Co-Authored-By: claude-flow
+```
+
+Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`
+
+## Security
+
+### Critical Rules
+- NEVER commit secrets, credentials, or .env files
+- NEVER hardcode API keys
+- Always validate user input
+- Use parameterized queries for SQL
+- Sanitize output to prevent XSS
+
+### Path Security
+- Validate all file paths
+- Prevent directory traversal (../)
+- Use absolute paths internally
+
+## Memory System
+
+### Storing Patterns
+```bash
+npx @claude-flow/cli memory store \
+ --key "pattern-name" \
+ --value "pattern description" \
+ --namespace patterns
+```
+
+### Searching Memory
+```bash
+npx @claude-flow/cli memory search \
+ --query "search terms" \
+ --namespace patterns
+```
+
+## Links
+
+- Documentation: https://github.com/ruvnet/claude-flow
+- Issues: https://github.com/ruvnet/claude-flow/issues
diff --git a/bindboxgame_api b/bindboxgame_api
new file mode 100755
index 0000000..5d2c3f7
Binary files /dev/null and b/bindboxgame_api differ
diff --git a/cmd/channel_stats_compare/detail.go b/cmd/channel_stats_compare/detail.go
new file mode 100644
index 0000000..058c2cd
--- /dev/null
+++ b/cmd/channel_stats_compare/detail.go
@@ -0,0 +1,61 @@
+package main
+
+import (
+ "fmt"
+
+ "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+)
+
+func main() {
+ dsn := "root:bindbox2025kdy@tcp(150.158.78.154:3306)/dev_game?charset=utf8mb4&parseTime=True&loc=Local"
+ db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
+
+ channelID := 3
+ filter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ type SourceStat struct {
+ SourceType int32
+ HasRemark string
+ Count int64
+ TotalCents int64
+ }
+ var stats []SourceStat
+ db.Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.source_type, CASE WHEN orders.remark LIKE '%lottery:activity:%' OR orders.remark LIKE '%activity:%' THEN 'Y' ELSE 'N' END as has_remark, COUNT(*) as count, SUM(orders.actual_amount) as total_cents").
+ Where(filter, channelID).
+ Group("orders.source_type, has_remark").
+ Order("orders.source_type, has_remark").
+ Scan(&stats)
+
+ fmt.Println("source_type: 1=直购, 2=抽奖, 3=翻牌, 4=一番赏")
+ fmt.Printf("%-12s %-12s %-10s %-15s\n", "source_type", "有remark", "订单数", "actual_amount(分)")
+ fmt.Println("---------------------------------------------------")
+ for _, s := range stats {
+ fmt.Printf("%-12d %-12s %-10d %-15d\n", s.SourceType, s.HasRemark, s.Count, s.TotalCents)
+ }
+
+ type Sample struct {
+ ID int64
+ SourceType int32
+ ActualAmount int64
+ Remark string
+ }
+ var samples []Sample
+ db.Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.id, orders.source_type, orders.actual_amount, orders.remark").
+ Where(filter+" AND (orders.remark = '' OR orders.remark NOT LIKE '%activity:%')", channelID).
+ Limit(10).
+ Scan(&samples)
+
+ fmt.Println("\n无 activity remark 的订单示例:")
+ for _, s := range samples {
+ rmk := s.Remark
+ if len(rmk) > 80 {
+ rmk = rmk[:80] + "..."
+ }
+ fmt.Printf(" ID=%-6d type=%d amount=%-8d remark=[%s]\n", s.ID, s.SourceType, s.ActualAmount, rmk)
+ }
+}
diff --git a/cmd/channel_stats_compare/ichiban.go b/cmd/channel_stats_compare/ichiban.go
new file mode 100644
index 0000000..a49dc92
--- /dev/null
+++ b/cmd/channel_stats_compare/ichiban.go
@@ -0,0 +1,55 @@
+package main
+
+import (
+ "fmt"
+
+ "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+)
+
+func main() {
+ dsn := "root:bindbox2025kdy@tcp(150.158.78.154:3306)/dev_game?charset=utf8mb4&parseTime=True&loc=Local"
+ db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
+
+ channelID := 3
+ filter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ type Sample struct {
+ ID int64
+ SourceType int32
+ ActualAmount int64
+ Remark string
+ }
+
+ // 一番赏 remark
+ var ichiban []Sample
+ db.Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.id, orders.source_type, orders.actual_amount, orders.remark").
+ Where(filter+" AND orders.source_type = 4", channelID).
+ Limit(5).
+ Scan(&ichiban)
+
+ fmt.Println("=== 一番赏 (source_type=4) remark 示例 ===")
+ for _, s := range ichiban {
+ fmt.Printf(" ID=%-6d amount=%-8d remark=[%s]\n", s.ID, s.ActualAmount, s.Remark)
+ }
+
+ // 翻牌 matching_game 的 issue 对应关系
+ type IssueActivity struct {
+ IssueID int64
+ ActivityID int64
+ PriceDraw int64
+ }
+ var ia []IssueActivity
+ db.Table("activity_issues").
+ Joins("JOIN activities ON activities.id = activity_issues.activity_id").
+ Select("activity_issues.id as issue_id, activity_issues.activity_id, activities.price_draw").
+ Where("activity_issues.id IN (92, 96, 104)").
+ Scan(&ia)
+
+ fmt.Println("\n=== 翻牌 issue → activity → price_draw ===")
+ for _, r := range ia {
+ fmt.Printf(" issue_id=%d → activity_id=%d → price_draw=%d\n", r.IssueID, r.ActivityID, r.PriceDraw)
+ }
+}
diff --git a/cmd/channel_stats_compare/main.go b/cmd/channel_stats_compare/main.go
new file mode 100644
index 0000000..106b0d1
--- /dev/null
+++ b/cmd/channel_stats_compare/main.go
@@ -0,0 +1,199 @@
+package main
+
+import (
+ "fmt"
+ "strings"
+
+ "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+)
+
+func main() {
+ dsn := "root:bindbox2025kdy@tcp(150.158.78.154:3306)/dev_game?charset=utf8mb4&parseTime=True&loc=Local"
+ db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
+ if err != nil {
+ fmt.Println("连接失败:", err)
+ return
+ }
+
+ channelID := 3
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ // 1. actual_amount 统计
+ type AmountResult struct {
+ OrderCount int64
+ TotalCents int64
+ }
+ var ar AmountResult
+ db.Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("COUNT(DISTINCT orders.id) as order_count, COALESCE(SUM(orders.actual_amount), 0) as total_cents").
+ Where(orderFilter, channelID).
+ Scan(&ar)
+
+ fmt.Println("========================================")
+ fmt.Printf("渠道 %d 数据对比\n", channelID)
+ fmt.Println("========================================")
+ fmt.Println()
+ fmt.Println("【方式1】SUM(actual_amount) — 用户实际支付")
+ fmt.Printf(" 订单数: %d\n", ar.OrderCount)
+ fmt.Printf(" 金额: %d 分 = %.2f 元\n", ar.TotalCents, float64(ar.TotalCents)/100)
+ fmt.Println()
+
+ // 2. 取所有订单的 remark,Go 中解析
+ type RemarkRow struct {
+ Remark string
+ }
+ var remarks []RemarkRow
+ db.Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.remark").
+ Where(orderFilter, channelID).
+ Scan(&remarks)
+
+ // 解析 remark 收集 activityIDs
+ type parsed struct {
+ activityID int64
+ count int64
+ }
+ var items []parsed
+ idSet := make(map[int64]struct{})
+ noRemarkCount := 0
+
+ for _, r := range remarks {
+ aid, cnt := parseRemark(r.Remark)
+ if aid > 0 {
+ items = append(items, parsed{activityID: aid, count: cnt})
+ idSet[aid] = struct{}{}
+ } else {
+ noRemarkCount++
+ }
+ }
+
+ // 批量查 price_draw(含软删除)
+ actIDs := make([]int64, 0, len(idSet))
+ for id := range idSet {
+ actIDs = append(actIDs, id)
+ }
+
+ type ActPrice struct {
+ ID int64
+ PriceDraw int64
+ }
+ priceMap := make(map[int64]int64)
+ if len(actIDs) > 0 {
+ var acts []ActPrice
+ db.Unscoped().Table("activities").
+ Select("id, price_draw").
+ Where("id IN ?", actIDs).
+ Find(&acts)
+ for _, a := range acts {
+ priceMap[a.ID] = a.PriceDraw
+ }
+ }
+
+ // 计算 price_draw × count
+ var totalPriceDraw int64
+ matchedCount := 0
+ unmatchedCount := 0
+ for _, item := range items {
+ if price, ok := priceMap[item.activityID]; ok {
+ totalPriceDraw += price * item.count
+ matchedCount++
+ } else {
+ unmatchedCount++
+ }
+ }
+
+ fmt.Println("【方式2】price_draw × count — 门票原价(当前实现)")
+ fmt.Printf(" 有效订单: %d (有 remark 且匹配活动)\n", matchedCount)
+ fmt.Printf(" 无 remark: %d\n", noRemarkCount)
+ fmt.Printf(" 活动不存在: %d\n", unmatchedCount)
+ fmt.Printf(" 金额: %d 分 = %.2f 元\n", totalPriceDraw, float64(totalPriceDraw)/100)
+ fmt.Println()
+
+ // 3. 差额
+ diff := totalPriceDraw - ar.TotalCents
+ fmt.Println("【差异分析】")
+ fmt.Printf(" price_draw×count - actual_amount = %d 分 = %.2f 元\n", diff, float64(diff)/100)
+ if diff > 0 {
+ fmt.Printf(" 说明: 用户总共享受了 %.2f 元优惠(优惠券/积分/折扣)\n", float64(diff)/100)
+ } else if diff < 0 {
+ fmt.Printf(" 说明: actual_amount 比 price_draw×count 多 %.2f 元(可能有额外费用)\n", float64(-diff)/100)
+ } else {
+ fmt.Println(" 说明: 两者完全一致,无优惠抵扣")
+ }
+ fmt.Println()
+
+ // 4. 抽样展示前10条差异订单
+ type DetailRow struct {
+ OrderID int64
+ ActualAmount int64
+ Remark string
+ }
+ var details []DetailRow
+ db.Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.id as order_id, orders.actual_amount, orders.remark").
+ Where(orderFilter, channelID).
+ Limit(200).
+ Scan(&details)
+
+ fmt.Println("【差异订单抽样(前10条有差异的)】")
+ fmt.Printf("%-10s %-15s %-15s %-10s %s\n", "订单ID", "actual_amount", "price×count", "差额", "remark摘要")
+ fmt.Println(strings.Repeat("-", 90))
+ shown := 0
+ for _, d := range details {
+ aid, cnt := parseRemark(d.Remark)
+ if aid <= 0 {
+ continue
+ }
+ price, ok := priceMap[aid]
+ if !ok {
+ continue
+ }
+ priceTotal := price * cnt
+ orderDiff := priceTotal - d.ActualAmount
+ if orderDiff != 0 && shown < 10 {
+ remarkShort := d.Remark
+ if len(remarkShort) > 40 {
+ remarkShort = remarkShort[:40] + "..."
+ }
+ fmt.Printf("%-10d %-15d %-15d %-10d %s\n", d.OrderID, d.ActualAmount, priceTotal, orderDiff, remarkShort)
+ shown++
+ }
+ }
+ if shown == 0 {
+ fmt.Println(" (前200条订单中无差异)")
+ }
+}
+
+func parseRemark(rm string) (activityID, count int64) {
+ count = 1
+ parts := strings.Split(rm, "|")
+ for _, p := range parts {
+ if strings.HasPrefix(p, "lottery:activity:") {
+ activityID = parseInt64(p[17:])
+ } else if strings.HasPrefix(p, "activity:") {
+ activityID = parseInt64(p[9:])
+ } else if strings.HasPrefix(p, "count:") {
+ n := parseInt64(p[6:])
+ if n > 0 {
+ count = n
+ }
+ }
+ }
+ return
+}
+
+func parseInt64(s string) int64 {
+ var n int64
+ for _, c := range s {
+ if c >= '0' && c <= '9' {
+ n = n*10 + int64(c-'0')
+ } else {
+ break
+ }
+ }
+ return n
+}
diff --git a/cmd/channel_stats_compare/profit_loss.go b/cmd/channel_stats_compare/profit_loss.go
index ee306ce..a04ecb4 100644
--- a/cmd/channel_stats_compare/profit_loss.go
+++ b/cmd/channel_stats_compare/profit_loss.go
@@ -40,6 +40,7 @@ func main() {
Where("COALESCE(user_inventory.remark, '') NOT LIKE ?", "%void%").
Where("(orders.status = 2 OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)").
Where("(orders.source_type IN (1,2,3,4) OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)").
+ Where("(orders.actual_amount > 0 OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)").
Scan(&rows)
var totalCostBase, totalCostFinal int64
@@ -128,6 +129,7 @@ func main() {
Where("COALESCE(user_inventory.remark, '') NOT LIKE ?", "%void%").
Where("(orders.status = 2 OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)").
Where("(orders.source_type IN (1,2,3,4) OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)").
+ Where("(orders.actual_amount > 0 OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)").
Where("system_item_cards.id IS NOT NULL").
Group("system_item_cards.id").
Scan(&cards)
diff --git a/cmd/channel_stats_compare/verify.go b/cmd/channel_stats_compare/verify.go
new file mode 100644
index 0000000..a866da3
--- /dev/null
+++ b/cmd/channel_stats_compare/verify.go
@@ -0,0 +1,246 @@
+package main
+
+import (
+ "fmt"
+ "strings"
+
+ "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+
+ "bindbox-game/internal/pkg/util/remark"
+)
+
+func main() {
+ dsn := "root:bindbox2025kdy@tcp(150.158.78.154:3306)/dev_game?charset=utf8mb4&parseTime=True&loc=Local"
+ db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
+ if err != nil {
+ fmt.Println("连接失败:", err)
+ return
+ }
+
+ channelID := 3
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ // 1. 查所有订单 remark + source_type
+ type RemarkRow struct {
+ ID int64
+ Remark string
+ SourceType int32
+ }
+ var rows []RemarkRow
+ db.Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.id, orders.remark, orders.source_type").
+ Where(orderFilter, channelID).
+ Scan(&rows)
+
+ fmt.Printf("渠道 %d 总有效订单: %d\n\n", channelID, len(rows))
+
+ // 2. 三路分类统计
+ var case1, case2, case3, unmatched int
+ actIDSet := make(map[int64]struct{})
+ issueIDSet := make(map[int64]struct{})
+ pkgIDSet := make(map[int64]struct{})
+
+ type parsed struct {
+ orderID int64
+ caseType int
+ activityID int64
+ issueID int64
+ pkgID int64
+ count int64
+ }
+ var items []parsed
+
+ for _, r := range rows {
+ rmk := remark.Parse(r.Remark)
+ p := parsed{orderID: r.ID, count: rmk.Count}
+
+ if rmk.ActivityID > 0 {
+ p.caseType = 1
+ p.activityID = rmk.ActivityID
+ actIDSet[rmk.ActivityID] = struct{}{}
+ case1++
+ } else if rmk.IssueID > 0 {
+ p.caseType = 2
+ p.issueID = rmk.IssueID
+ issueIDSet[rmk.IssueID] = struct{}{}
+ case2++
+ } else if rmk.PkgID > 0 {
+ p.caseType = 3
+ p.pkgID = rmk.PkgID
+ pkgIDSet[rmk.PkgID] = struct{}{}
+ case3++
+ } else {
+ unmatched++
+ }
+ items = append(items, p)
+ }
+
+ fmt.Println("=== 三路分类统计 ===")
+ fmt.Printf(" Case1 (抽奖/直购, ActivityID>0): %d 笔\n", case1)
+ fmt.Printf(" Case2 (对对碰, IssueID>0): %d 笔\n", case2)
+ fmt.Printf(" Case3 (一番赏, PkgID>0): %d 笔\n", case3)
+ fmt.Printf(" 未匹配: %d 笔\n", unmatched)
+ fmt.Println()
+
+ // 3. 查 activity_issues (Case2)
+ issueActivityMap := make(map[int64]int64)
+ if len(issueIDSet) > 0 {
+ issueIDs := make([]int64, 0, len(issueIDSet))
+ for id := range issueIDSet {
+ issueIDs = append(issueIDs, id)
+ }
+ type IssueRow struct {
+ ID int64
+ ActivityID int64
+ }
+ var issueRows []IssueRow
+ db.Table("activity_issues").
+ Select("id, activity_id").
+ Where("id IN ?", issueIDs).
+ Scan(&issueRows)
+ for _, ir := range issueRows {
+ issueActivityMap[ir.ID] = ir.ActivityID
+ actIDSet[ir.ActivityID] = struct{}{}
+ }
+ fmt.Printf("activity_issues 查到: %d / %d\n", len(issueRows), len(issueIDs))
+ }
+
+ // 4. 查 activities.price_draw (Case1+2)
+ priceMap := make(map[int64]int64)
+ if len(actIDSet) > 0 {
+ actIDs := make([]int64, 0, len(actIDSet))
+ for id := range actIDSet {
+ actIDs = append(actIDs, id)
+ }
+ type ActRow struct {
+ ID int64
+ PriceDraw int64
+ }
+ var actRows []ActRow
+ db.Unscoped().Table("activities").
+ Select("id, price_draw").
+ Where("id IN ?", actIDs).
+ Scan(&actRows)
+ for _, a := range actRows {
+ priceMap[a.ID] = a.PriceDraw
+ }
+ fmt.Printf("activities 查到: %d / %d\n", len(actRows), len(actIDs))
+ }
+
+ // 5. 查 game_pass_packages.price (Case3)
+ pkgPriceMap := make(map[int64]int64)
+ if len(pkgIDSet) > 0 {
+ pkgIDs := make([]int64, 0, len(pkgIDSet))
+ for id := range pkgIDSet {
+ pkgIDs = append(pkgIDs, id)
+ }
+ type PkgRow struct {
+ ID int64
+ Price int64
+ }
+ var pkgRows []PkgRow
+ db.Unscoped().Table("game_pass_packages").
+ Select("id, price").
+ Where("id IN ?", pkgIDs).
+ Scan(&pkgRows)
+ for _, p := range pkgRows {
+ pkgPriceMap[p.ID] = p.Price
+ }
+ fmt.Printf("game_pass_packages 查到: %d / %d\n", len(pkgRows), len(pkgIDs))
+ }
+ fmt.Println()
+
+ // 6. 计算金额
+ var totalCase1, totalCase2, totalCase3 int64
+ var matchedCase1, matchedCase2, matchedCase3 int
+ var unmatchedCase1, unmatchedCase2, unmatchedCase3 int
+
+ for _, item := range items {
+ switch item.caseType {
+ case 1:
+ if price, ok := priceMap[item.activityID]; ok {
+ totalCase1 += price * item.count
+ matchedCase1++
+ } else {
+ unmatchedCase1++
+ }
+ case 2:
+ if actID, ok := issueActivityMap[item.issueID]; ok {
+ if price, ok := priceMap[actID]; ok {
+ totalCase2 += price * item.count
+ matchedCase2++
+ } else {
+ unmatchedCase2++
+ }
+ } else {
+ unmatchedCase2++
+ }
+ case 3:
+ if price, ok := pkgPriceMap[item.pkgID]; ok {
+ totalCase3 += price * item.count
+ matchedCase3++
+ } else {
+ unmatchedCase3++
+ }
+ }
+ }
+
+ total := totalCase1 + totalCase2 + totalCase3
+
+ fmt.Println("=== 金额统计 (price_draw/price × count) ===")
+ fmt.Printf(" Case1 抽奖/直购: %d 分 = %.2f 元 (匹配 %d, 未匹配 %d)\n",
+ totalCase1, float64(totalCase1)/100, matchedCase1, unmatchedCase1)
+ fmt.Printf(" Case2 对对碰: %d 分 = %.2f 元 (匹配 %d, 未匹配 %d)\n",
+ totalCase2, float64(totalCase2)/100, matchedCase2, unmatchedCase2)
+ fmt.Printf(" Case3 一番赏: %d 分 = %.2f 元 (匹配 %d, 未匹配 %d)\n",
+ totalCase3, float64(totalCase3)/100, matchedCase3, unmatchedCase3)
+ fmt.Println(strings.Repeat("-", 60))
+ fmt.Printf(" 合计: %d 分 = %.2f 元\n", total, float64(total)/100)
+ fmt.Printf(" 覆盖订单: %d / %d (%.1f%%)\n",
+ matchedCase1+matchedCase2+matchedCase3, len(rows),
+ float64(matchedCase1+matchedCase2+matchedCase3)/float64(len(rows))*100)
+ fmt.Println()
+
+ // 7. 对比 actual_amount
+ type AmountResult struct {
+ TotalCents int64
+ }
+ var ar AmountResult
+ db.Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("COALESCE(SUM(orders.actual_amount), 0) as total_cents").
+ Where(orderFilter, channelID).
+ Scan(&ar)
+
+ fmt.Println("=== 对比 ===")
+ fmt.Printf(" SUM(actual_amount): %d 分 = %.2f 元\n", ar.TotalCents, float64(ar.TotalCents)/100)
+ fmt.Printf(" price_draw/price × count: %d 分 = %.2f 元\n", total, float64(total)/100)
+ diff := total - ar.TotalCents
+ fmt.Printf(" 差额: %d 分 = %.2f 元\n", diff, float64(diff)/100)
+ if diff > 0 {
+ fmt.Printf(" 说明: 用户享受了 %.2f 元优惠\n", float64(diff)/100)
+ }
+
+ // 8. 打印未匹配订单示例
+ if unmatched > 0 {
+ fmt.Printf("\n=== 未匹配 remark 示例 (共 %d 笔) ===\n", unmatched)
+ shown := 0
+ for _, item := range items {
+ if item.caseType == 0 && shown < 5 {
+ for _, r := range rows {
+ if r.ID == item.orderID {
+ rmk := r.Remark
+ if len(rmk) > 80 {
+ rmk = rmk[:80] + "..."
+ }
+ fmt.Printf(" ID=%-6d type=%d remark=[%s]\n", r.ID, r.SourceType, rmk)
+ shown++
+ break
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/cmd/debug_check_coupon_22/main.go b/cmd/debug_check_coupon_22/main.go
index df03844..d0686b9 100755
--- a/cmd/debug_check_coupon_22/main.go
+++ b/cmd/debug_check_coupon_22/main.go
@@ -1,12 +1,13 @@
package main
import (
- "bindbox-game/configs"
- "bindbox-game/internal/repository/mysql"
- "bindbox-game/internal/repository/mysql/dao"
"context"
"flag"
"fmt"
+
+ "bindbox-game/configs"
+ "bindbox-game/internal/repository/mysql"
+ "bindbox-game/internal/repository/mysql/dao"
)
func main() {
diff --git a/cmd/douyin_sync_debug/main.go b/cmd/douyin_sync_debug/main.go
index 6c5bb42..ce1b698 100644
--- a/cmd/douyin_sync_debug/main.go
+++ b/cmd/douyin_sync_debug/main.go
@@ -64,7 +64,7 @@ func main() {
env.Active() // 初始化 env flag(依赖已有的全局 -env/ACTIVE_ENV 配置)
configs.Init()
- cookie := "s_v_web_id=verify_mm0pjkt7_rRCYDU7B_F5Yl_4UYj_8yQ0_ue0vAcKwYt3z; csrf_session_id=86df5285aa04dec74fe5ac89d1b0d5c0; passport_csrf_token=fe2b51efeb70763190b402f49ad9f0e9; passport_csrf_token_default=fe2b51efeb70763190b402f49ad9f0e9; x-web-secsdk-uid=749f802e-47b8-4221-98af-b726e5631036; Hm_lvt_b6520b076191ab4b36812da4c90f7a5e=1771943727; HMACCOUNT=74DD13C46DE836FC; ttcid=c1ec90610ace481ba60dd8303b332c8e40; odin_tt=f01a3108f23b93c70d9d41eb2536553aa6550eb007cfc2bc3ba6319e82ad90eef45e1f581adbb6d1fb1fc2bdcce6d8cdd72b475fa9943bab1df0efe1ea035355; passport_auth_status=07988630820adb6946c4969658ab8b4d%2C; passport_auth_status_ss=07988630820adb6946c4969658ab8b4d%2C; uid_tt=f8cbc1387650f5a331a9a2943293d5f2; uid_tt_ss=f8cbc1387650f5a331a9a2943293d5f2; sid_tt=d1e48959ea47e34970be1d9b0aa801a2; sessionid=d1e48959ea47e34970be1d9b0aa801a2; sessionid_ss=d1e48959ea47e34970be1d9b0aa801a2; is_staff_user=false; PHPSESSID=294f6cf83ec2a4fefc1222321590b3e7; PHPSESSID_SS=294f6cf83ec2a4fefc1222321590b3e7; ucas_c0=CkEKBTEuMC4wEKOIj97Q5-3OaRjmJiD61rDnqc2DBCiwITCb1oDYuM3aB0DL7vbMBkjLorPPBlC_vL6Ekt3t1GdYbhIUPQw_elr7IsxkcNFj3v1rRHn03qs; ucas_c0_ss=CkEKBTEuMC4wEKOIj97Q5-3OaRjmJiD61rDnqc2DBCiwITCb1oDYuM3aB0DL7vbMBkjLorPPBlC_vL6Ekt3t1GdYbhIUPQw_elr7IsxkcNFj3v1rRHn03qs; ecom_gray_shop_id=156231010; sid_guard=d1e48959ea47e34970be1d9b0aa801a2%7C1772108860%7C5184000%7CMon%2C+27-Apr-2026+12%3A27%3A40+GMT; session_tlb_tag=sttt%7C9%7C0eSJWepH40lwvh2bCqgBov_________yZl6I8Equ6hjlsXft1nWEmcwpzFQYKIutCIRtYdHffp0%3D; sid_ucp_v1=1.0.0-KDc4Mjc1ZjFkNTg4NjFkZWQwYjUzMTJmNWFjN2U4ZmM1NzYzODEwNTcKGQib1oDYuM3aBxC8-IDNBhiwISAMOAZA9AcaAmxmIiBkMWU0ODk1OWVhNDdlMzQ5NzBiZTFkOWIwYWE4MDFhMg; ssid_ucp_v1=1.0.0-KDc4Mjc1ZjFkNTg4NjFkZWQwYjUzMTJmNWFjN2U4ZmM1NzYzODEwNTcKGQib1oDYuM3aBxC8-IDNBhiwISAMOAZA9AcaAmxmIiBkMWU0ODk1OWVhNDdlMzQ5NzBiZTFkOWIwYWE4MDFhMg; COMPASS_LUOPAN_DT=session_7611148681122726154; BUYIN_SASID=SID2_7611148178737856777; gfkadpd=4272,23756; zsgw_business_data=%7B%22uuid%22%3A%2267d1b0e4-dca5-484d-997a-b70cb555e396%22%2C%22platform%22%3A%22pc%22%2C%22source%22%3A%22seo.google%22%7D; source=seo.google; Hm_lpvt_b6520b076191ab4b36812da4c90f7a5e=1772115439; ttwid=1%7C71OUHp7yB34JMc3dVW9XMZxKJfcmzgfSzG407fx6Gqo%7C1772115438%7C5c6372575550a6bddb3a4eb25fff2fdc9f0d0954e0ce795eb1eb15e121a9ca53; tt_scid=bAGxaUh7d5HftS77rQMVwbdERMWrYT63ZZMLaRlsZiLgbOweJMjw-1IEYQvEO1Qz836d; op_session="
+ cookie := "passport_csrf_token=40ba4a1be914a9f167320ed28b8c93d7; passport_csrf_token_default=40ba4a1be914a9f167320ed28b8c93d7; is_staff_user=false; s_v_web_id=verify_mkf83bbo_zfQ3q1Gp_5irf_4OOI_9y4N_C253269yUIJy; SHOP_ID=156231010; PIGEON_CID=4339134776748827; __security_mc_1_s_sdk_crypt_sdk=db47f387-4d0b-bf21; bd_ticket_guard_client_web_domain=2; bd_ticket_guard_client_data=eyJiZC10aWNrZXQtZ3VhcmQtdmVyc2lvbiI6MiwiYmQtdGlja2V0LWd1YXJkLWl0ZXJhdGlvbi12ZXJzaW9uIjoxLCJiZC10aWNrZXQtZ3VhcmQtcmVlLXB1YmxpYy1rZXkiOiJCTHVTREdkVFRHWUdNMVY3ZDZKS2M4V2FwWGJ1K3JVYmVqRThONTZoeTI4SUJXdmVxZjBLMS9GczE0dWx5RTVRd2d4cjdnaDd6SXdMZjlsWDkwOFZQQWs9IiwiYmQtdGlja2V0LWd1YXJkLXdlYi12ZXJzaW9uIjoyfQ%3D%3D; bd_ticket_guard_web_domain=3; gfkadpd=4272,23756; ecom_gray_shop_id=156231010; zsgw_business_data=%7B%22uuid%22%3A%226756720f-c380-4bda-ab81-3dd27ca08a2d%22%2C%22platform%22%3A%22pc%22%2C%22source%22%3A%22seo.baidu.069%22%7D; source=seo.baidu.069; Hm_lvt_b6520b076191ab4b36812da4c90f7a5e=1771350555,1772107597,1772794481,1773223394; HMACCOUNT=9C6B7571794A6624; csrf_session_id=8173f094b830570b2b64e98900924731; passport_mfa_token=CjcMUe8O6Zz52W9O1T3zlEkIxpWSHBCB4dHw9XBdiDU%2BIPU1pzwEXLpVjGth2W2nXGHC8OM6ffSmGkoKPAAAAAAAAAAAAABQK6uUDAbmPNiLgEkCaMWLdiWMpTEiK%2Fm1NGLpqOUmR4vBZtoNbJWrAhzjfim%2BBtfMlxCj6IsOGPax0WwgAiIBA8pTDDU%3D; Hm_lpvt_b6520b076191ab4b36812da4c90f7a5e=1773224382; ttwid=1%7CNnXcElGkMBE8UTpDOFYR5OfCUYkFjQaLyn1EagPBZgM%7C1773224307%7C18bc27eb78d0a5da332f8c3ec951f81229670377d82025fcb5e600e3766e367b; tt_scid=uSkT0B7AzW.AKqYpEsRrpTqtws.7fqp2P4-gBF1FyffuNMOl1AKuRvuymbUWzXRvcc00; odin_tt=6edadb78040b4604bed517fc3edef437495387c8a3bf60fa177788ff81dd88daaed661705eb0729801e665c086b098b263c3090fef72c26e872d2f3172f6e364; passport_auth_status=581a8676e64d918c69ee3930f4dacf8b%2C4bb14205ac4179b872cba76a97208a7e; passport_auth_status_ss=581a8676e64d918c69ee3930f4dacf8b%2C4bb14205ac4179b872cba76a97208a7e; bd_ticket_guard_server_data=eyJ0aWNrZXQiOiJoYXNoLk1SWGtrczRwYTZpWG91ODhuZENOT05idm9iSjI2SHlXOXRYN2JKNTdZMWM9IiwidHNfc2lnbiI6InRzLjIuMDg1MDhmMjljNWI2MjkzMjQ4ZTAwNGY0YjdiNjMwODI4ODk1YjFkZWQ1ZTRlYmFiZTc3NmYzZTUxYWJjZjZhNGM0ZmJlODdkMjMxOWNmMDUzMTg2MjRjZWRhMTQ5MTFjYTQwNmRlZGJlYmVkZGIyZTMwZmNlOGQ0ZmEwMjU3NWQiLCJjbGllbnRfY2VydCI6InB1Yi5CTHVTREdkVFRHWUdNMVY3ZDZKS2M4V2FwWGJ1K3JVYmVqRThONTZoeTI4SUJXdmVxZjBLMS9GczE0dWx5RTVRd2d4cjdnaDd6SXdMZjlsWDkwOFZQQWs9IiwibG9nX2lkIjoiMjAyNjAzMTExODE4NDBGQUVGNkZGMDBCMkUwQTJEQTU2QSIsImNyZWF0ZV90aW1lIjoxNzczMjI0MzIwfQ%3D%3D; uid_tt=e8ca5ad2e6032b72a0fd8c0843ff5e9b; uid_tt_ss=e8ca5ad2e6032b72a0fd8c0843ff5e9b; sid_tt=c1a29f1f0f71ea4ed9fbcde60bc2b390; sessionid=c1a29f1f0f71ea4ed9fbcde60bc2b390; sessionid_ss=c1a29f1f0f71ea4ed9fbcde60bc2b390; PHPSESSID=05ca4c3439dacd9ac5f1d86a78516abb; PHPSESSID_SS=05ca4c3439dacd9ac5f1d86a78516abb; ucas_c0=CkEKBTEuMC4wELaIgqLTr9DYaRjmJiD61rDnqc2DBCiwITCb1oDYuM3aB0CCg8XNBkiCt4HQBlC_vL6Ekt3t1GdYbhIUI1wJXqAsE71YWUNwS6OvJ9dOEVE; ucas_c0_ss=CkEKBTEuMC4wELaIgqLTr9DYaRjmJiD61rDnqc2DBCiwITCb1oDYuM3aB0CCg8XNBkiCt4HQBlC_vL6Ekt3t1GdYbhIUI1wJXqAsE71YWUNwS6OvJ9dOEVE; sid_guard=c1a29f1f0f71ea4ed9fbcde60bc2b390%7C1773224328%7C5184000%7CSun%2C+10-May-2026+10%3A18%3A48+GMT; sid_ucp_v1=1.0.0-KDA3MGQyMjJkNmQ1NDUxOGQ1MWRhYTFjMzBkZTZkMDBlMTNlYWJhYWUKGwib1oDYuM3aBxCIg8XNBhiwISAMOAZA9AdIBBoCaGwiIGMxYTI5ZjFmMGY3MWVhNGVkOWZiY2RlNjBiYzJiMzkw; ssid_ucp_v1=1.0.0-KDA3MGQyMjJkNmQ1NDUxOGQ1MWRhYTFjMzBkZTZkMDBlMTNlYWJhYWUKGwib1oDYuM3aBxCIg8XNBhiwISAMOAZA9AdIBBoCaGwiIGMxYTI5ZjFmMGY3MWVhNGVkOWZiY2RlNjBiYzJiMzkw; session_tlb_tag=sttt%7C17%7CwaKfHw9x6k7Z-83mC8KzkP________-tSxexYwusSRjOrIMuB3YiA6EaLnfr1fbbR8LfwAsAu74%3D; BUYIN_SASID=SID2_7615938059562205474; COMPASS_LUOPAN_DT=session_7615939876688511241"
if cookie == "" {
fmt.Println("请通过环境变量 DOUYIN_COOKIE 提供抖店 Cookie")
os.Exit(1)
diff --git a/cmd/exploit_verify/main.go b/cmd/exploit_verify/main.go
new file mode 100644
index 0000000..e26adad
--- /dev/null
+++ b/cmd/exploit_verify/main.go
@@ -0,0 +1,219 @@
+package main
+
+import (
+ "database/sql"
+ "fmt"
+ "os"
+ "strings"
+ "time"
+
+ _ "github.com/go-sql-driver/mysql"
+)
+
+func main() {
+ dsn := "root:bindbox2025kdy@tcp(150.158.78.154:3306)/dev_game?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai"
+ db, err := sql.Open("mysql", dsn)
+ if err != nil {
+ fmt.Println("连接失败:", err)
+ os.Exit(1)
+ }
+ defer db.Close()
+ fmt.Println("✅ 数据库连接成功\n")
+
+ // ============ 1. 全局汇总 ============
+ fmt.Println("【1】全局汇总")
+ var userCount, itemCount int64
+ var totalYuan float64
+ db.QueryRow(`
+ SELECT COUNT(DISTINCT t.to_user_id), COUNT(DISTINCT t.inventory_id), IFNULL(SUM(i.value_cents)/100.0, 0)
+ FROM user_inventory_transfers t
+ JOIN user_inventory i ON i.id = t.inventory_id
+ WHERE i.remark LIKE '%redeemed%'
+ `).Scan(&userCount, &itemCount, &totalYuan)
+ fmt.Printf(" 涉及用户: %d | 涉及资产: %d | 总薅取金额: %.2f 元\n\n", userCount, itemCount, totalYuan)
+
+ // ============ 2. 按用户汇总 ============
+ fmt.Println("【2】按用户汇总薅取金额")
+ fmt.Println(strings.Repeat("-", 95))
+ fmt.Printf(" %-8s %-16s %-15s %-10s %-12s %-12s %s\n",
+ "用户ID", "昵称", "手机号", "兑换资产数", "薅取金额(元)", "当前余额", "可扣回?")
+ fmt.Println(" " + strings.Repeat("-", 90))
+
+ rows2, _ := db.Query(`
+ SELECT
+ sub.user_id,
+ IFNULL(u.nickname, '') AS nickname,
+ IFNULL(u.mobile, '') AS mobile,
+ sub.redeem_count,
+ sub.total_yuan,
+ IFNULL(pts.balance, 0) AS balance
+ FROM (
+ SELECT t.to_user_id AS user_id,
+ COUNT(DISTINCT t.inventory_id) AS redeem_count,
+ SUM(i.value_cents) / 100.0 AS total_yuan,
+ SUM(i.value_cents) AS total_cents
+ FROM user_inventory_transfers t
+ JOIN user_inventory i ON i.id = t.inventory_id
+ WHERE i.remark LIKE '%redeemed%'
+ GROUP BY t.to_user_id
+ ) sub
+ LEFT JOIN users u ON u.id = sub.user_id
+ LEFT JOIN (SELECT user_id, SUM(points) AS balance FROM user_points GROUP BY user_id) pts ON pts.user_id = sub.user_id
+ ORDER BY sub.total_yuan DESC
+ `)
+ if rows2 != nil {
+ defer rows2.Close()
+ for rows2.Next() {
+ var uid, redeemCnt, balance int64
+ var totalY float64
+ var nick, mobile string
+ rows2.Scan(&uid, &nick, &mobile, &redeemCnt, &totalY, &balance)
+ canDeduct := "✅ 可全额"
+ exploitCents := int64(totalY * 100)
+ if balance < exploitCents {
+ canDeduct = fmt.Sprintf("⚠️ 仅可扣%d", balance)
+ }
+ fmt.Printf(" %-8d %-16s %-15s %-10d %-12.2f %-12d %s\n",
+ uid, nick, mobile, redeemCnt, totalY, balance, canDeduct)
+ }
+ }
+
+ // ============ 3. 并发漏洞证据 ============
+ fmt.Println("\n【3】并发漏洞证据 — 同一资产被多次转赠")
+ fmt.Println(strings.Repeat("-", 100))
+ rows3, _ := db.Query(`
+ SELECT t.inventory_id, COUNT(*) AS cnt,
+ GROUP_CONCAT(CONCAT(t.from_user_id,'→',t.to_user_id) ORDER BY t.created_at SEPARATOR ' | ') AS path,
+ i.value_cents, IFNULL(p.name,'') AS pname
+ FROM user_inventory_transfers t
+ JOIN user_inventory i ON i.id = t.inventory_id
+ LEFT JOIN products p ON p.id = i.product_id
+ GROUP BY t.inventory_id, i.value_cents, p.name
+ HAVING COUNT(*) > 1
+ ORDER BY cnt DESC, i.value_cents DESC
+ `)
+ if rows3 != nil {
+ defer rows3.Close()
+ fmt.Printf(" %-10s %-6s %-10s %-28s %s\n", "资产ID", "次数", "价值(元)", "商品", "转赠路径")
+ fmt.Println(" " + strings.Repeat("-", 95))
+ for rows3.Next() {
+ var invID, cnt, vc int64
+ var path, pname string
+ rows3.Scan(&invID, &cnt, &path, &vc, &pname)
+ if len([]rune(pname)) > 14 {
+ pname = string([]rune(pname)[:14]) + ".."
+ }
+ fmt.Printf(" %-10d %-6d %-10.2f %-28s %s\n", invID, cnt, float64(vc)/100.0, pname, path)
+ }
+ }
+
+ // ============ 4. 转赠关系网络 Top15 ============
+ fmt.Println("\n【4】转赠关系网络 Top15")
+ fmt.Println(strings.Repeat("-", 110))
+ rows4, _ := db.Query(`
+ SELECT t.from_user_id, IFNULL(fu.nickname,'') AS fn,
+ t.to_user_id, IFNULL(tu.nickname,'') AS tn,
+ COUNT(*) AS xfer_cnt, COUNT(DISTINCT t.inventory_id) AS item_cnt,
+ SUM(i.value_cents)/100.0 AS total_yuan,
+ MIN(t.created_at) AS first_t, MAX(t.created_at) AS last_t
+ FROM user_inventory_transfers t
+ JOIN user_inventory i ON i.id = t.inventory_id
+ LEFT JOIN users fu ON fu.id = t.from_user_id
+ LEFT JOIN users tu ON tu.id = t.to_user_id
+ GROUP BY t.from_user_id, fu.nickname, t.to_user_id, tu.nickname
+ ORDER BY total_yuan DESC LIMIT 15
+ `)
+ if rows4 != nil {
+ defer rows4.Close()
+ fmt.Printf(" %-20s → %-20s %-6s %-6s %-12s %-12s %-12s\n",
+ "赠送方", "接收方", "转赠次", "资产数", "金额(元)", "首次", "末次")
+ fmt.Println(" " + strings.Repeat("-", 105))
+ for rows4.Next() {
+ var fuid, tuid, xcnt, icnt int64
+ var yuan float64
+ var fn, tn string
+ var ft, lt time.Time
+ rows4.Scan(&fuid, &fn, &tuid, &tn, &xcnt, &icnt, &yuan, &ft, <)
+ from := fmt.Sprintf("%d(%s)", fuid, truncStr(fn, 6))
+ to := fmt.Sprintf("%d(%s)", tuid, truncStr(tn, 6))
+ fmt.Printf(" %-20s → %-20s %-6d %-6d %-12.2f %-12s %-12s\n",
+ from, to, xcnt, icnt, yuan,
+ ft.Format("01-02 15:04"), lt.Format("01-02 15:04"))
+ }
+ }
+
+ // ============ 5. 典型利用链路样本(前10条) ============
+ fmt.Println("\n【5】典型利用链路样本(转赠→取消发货→兑换积分)")
+ fmt.Println(strings.Repeat("-", 130))
+ rows5, _ := db.Query(`
+ SELECT i.id, i.user_id, IFNULL(u.nickname,'') AS nick,
+ i.value_cents, i.status, i.remark
+ FROM user_inventory i
+ LEFT JOIN users u ON u.id = i.user_id
+ WHERE i.remark LIKE '%transferred_from_%'
+ AND i.remark LIKE '%shipping_cancelled%'
+ AND i.remark LIKE '%redeemed%'
+ ORDER BY i.value_cents DESC
+ LIMIT 10
+ `)
+ if rows5 != nil {
+ defer rows5.Close()
+ fmt.Printf(" %-8s %-8s %-14s %-10s %-6s %s\n", "资产ID", "用户ID", "昵称", "价值(元)", "状态", "操作链路")
+ fmt.Println(" " + strings.Repeat("-", 125))
+ for rows5.Next() {
+ var id, uid, vc int64
+ var status int32
+ var nick, remark string
+ rows5.Scan(&id, &uid, &nick, &vc, &status, &remark)
+ fmt.Printf(" %-8d %-8d %-14s %-10.2f %-6s %s\n",
+ id, uid, truncStr(nick, 12), float64(vc)/100.0,
+ statusText(status), parseActions(remark))
+ }
+ }
+
+ fmt.Println("\n✅ 核对完毕")
+}
+
+func truncStr(s string, maxRunes int) string {
+ runes := []rune(s)
+ if len(runes) > maxRunes {
+ return string(runes[:maxRunes]) + ".."
+ }
+ return s
+}
+
+func parseActions(remark string) string {
+ parts := strings.Split(remark, "|")
+ actions := make([]string, 0, len(parts))
+ for _, p := range parts {
+ p = strings.TrimSpace(p)
+ if p == "" {
+ continue
+ }
+ if strings.HasPrefix(p, "transferred_from_") {
+ actions = append(actions, "转赠")
+ } else if p == "shipping_requested" {
+ actions = append(actions, "发货")
+ } else if strings.HasPrefix(p, "shipping_cancelled") {
+ actions = append(actions, "取消发货")
+ } else if strings.Contains(p, "redeemed") {
+ actions = append(actions, "✖兑换积分")
+ } else {
+ actions = append(actions, p)
+ }
+ }
+ return strings.Join(actions, " → ")
+}
+
+func statusText(s int32) string {
+ switch s {
+ case 1:
+ return "持有"
+ case 2:
+ return "作废"
+ case 3:
+ return "已用"
+ default:
+ return fmt.Sprintf("%d", s)
+ }
+}
diff --git a/docs/赠送资产漏洞核查报告.md b/docs/赠送资产漏洞核查报告.md
new file mode 100644
index 0000000..b84026d
--- /dev/null
+++ b/docs/赠送资产漏洞核查报告.md
@@ -0,0 +1,162 @@
+# 赠送资产漏洞核查报告
+
+> 数据源: dev_game 数据库 | 核查日期: 2026-03-11
+
+---
+
+## 一、结论摘要
+
+| 项目 | 结论 |
+|------|------|
+| 并发漏洞 | **确实存在**,已修复(SELECT FOR UPDATE + RowsAffected 检查) |
+| 实际货物损失(一份发两份) | **0 元** — 18 个重复发货资产中,没有一个真正被两方都发了货 |
+| 积分重复兑换 | **0 元** — 没有任何资产被多人兑换积分,也没有同一资产被兑换多次 |
+| 发送方转赠后又兑换同一资产 | **0 笔** — 发送方没有在转赠后兑换过同一资产 |
+| 转赠后接收方兑换积分 | 91 笔 / 12,088.80 元 — **合法行为**,资产转赠后归接收方所有 |
+
+**总实际损失: 0 元**
+
+---
+
+## 二、漏洞技术分析
+
+### 2.1 Bug 描述
+
+文件: `internal/service/user/address_share.go`
+
+| Bug | 位置 | 描述 | 后果 |
+|-----|------|------|------|
+| readDB 竞态 | 原 L116-133 | 反重复检查使用从库(readDB),主从延迟 10-100ms 内并发请求可绕过 | 同一资产产生重复转赠记录和重复发货记录 |
+| RowsAffected 未检查 | 原 L181-189 | `Updates()` 返回 0 行影响时不报错,后续操作继续执行 | 资产状态未变但发货记录已创建 |
+
+### 2.2 修复方案(已合并 zuncle 分支)
+
+| 修复 | 方式 |
+|------|------|
+| 竞态条件 | 在事务内使用 `SELECT FOR UPDATE` 锁行 + 写库查询发货记录 |
+| RowsAffected | 转赠和原主发货两个分支都检查 `result.RowsAffected == 0` 后回滚 |
+
+### 2.3 关于"转赠资产禁止兑换积分"
+
+zuncle 分支原本还包含第三个修复:禁止通过转赠获得的资产兑换积分。经核实,**这是业务策略而非修漏洞**:
+- 资产转赠后归接收方所有,接收方有权决定发货或兑换积分
+- 发送方没有对已转赠的资产做任何兑换操作
+- 不存在"一份资产两边都兑换"的情况
+
+**已回退此限制。**
+
+---
+
+## 三、数据核查
+
+### 3.1 全局概况
+
+| 指标 | 数值 |
+|------|------|
+| 总转赠记录数 | 157 条 |
+| 涉及资产数 | 135 个 |
+| 涉及用户数 | 15 人 |
+| 多次转赠资产 | 13 个(并发 bug 导致的重复记录) |
+| 两方都产生发货记录的资产 | 18 个 |
+
+### 3.2 重复发货资产明细(18 个)
+
+> 同一资产在发送方和接收方名下都产生了发货记录
+
+#### 仅接收方有效发货,发送方全取消(8 个)— 无损失
+
+| 资产ID | 价值(元) | 发送方 | 接收方 | 接收方状态 | 发送方状态 | 兑换积分 |
+|--------|---------|--------|--------|-----------|-----------|---------|
+| 49426 | 1,315.00 | 9248(不出last退了) | 9116(非洲人) | 有效1/取消1 | 全取消(2) | 否 |
+| 47096 | 900.00 | 9305(新人) | 9116(非洲人) | 有效1/取消1 | 全取消(3) | 否 |
+| 51038 | 605.00 | 9210(非酋) | 9116(非洲人) | 有效1/取消3 | 全取消(1) | 否 |
+| 44153 | 375.00 | 9248(不出last退了) | 9116(非洲人) | 有效1/取消2 | 全取消(1) | 否 |
+| 44152 | 375.00 | 9248(不出last退了) | 9116(非洲人) | 有效1/取消4 | 全取消(1) | 否 |
+| 44151 | 375.00 | 9248(不出last退了) | 9116(非洲人) | 有效1/取消2 | 全取消(1) | 否 |
+| 44150 | 375.00 | 9248(不出last退了) | 9116(非洲人) | 有效1/取消2 | 全取消(1) | 否 |
+
+小计: 4,320 元,全部仅接收方 9116 有效发货,**无实际损失**。
+
+#### 双方全取消(10 个)— 无损失
+
+| 资产ID | 价值(元) | 发送方 | 接收方 | 接收方兑换积分 |
+|--------|---------|--------|--------|------------|
+| 42746 | 375.00 | 9336(有冰的帝君) | 9116(非洲人) | 是 |
+| 42757 | 375.00 | 9336(有冰的帝君) | 9116(非洲人) | 是 |
+| 42758 | 375.00 | 9336(有冰的帝君) | 9116(非洲人) | 是 |
+| 43304 | 375.00 | 9305(新人) | 9116(非洲人) | 是 |
+| 42761 | 375.00 | 9116(非洲人) | 9305(新人) | 是 |
+| 46445 | 375.00 | 9230(巨欧小肥龙) | 9116(非洲人) | 是 |
+| 46446 | 375.00 | 9230(巨欧小肥龙) | 9116(非洲人) | 是 |
+| 46447 | 375.00 | 9230(巨欧小肥龙) | 9116(非洲人) | 是 |
+| 46506 | 375.00 | 9209(程c) | 9116(非洲人) | 是 |
+| 46507 | 375.00 | 9209(程c) | 9116(非洲人) | 是 |
+| 52338 | 12.50 | 9094(范巴斯滕) | 9449(古利特) | 是 |
+
+小计: 双方发货全取消,接收方后续兑换了积分 — 这属于**接收方对自有资产的合法操作**。
+
+### 3.3 积分兑换核查
+
+| 核查项 | 结果 |
+|--------|------|
+| 同一资产被多个用户兑换积分 | **0 个** |
+| 同一资产被同一用户多次兑换积分 | **0 个** |
+| 发送方在 points_ledger 中兑换已转赠资产 | **0 笔** |
+| 发送方的已转赠资产 remark 含 redeemed | **1 笔**(用户 9116 转出给 9305 的资产 43304,后又转回 9116 兑换,属于正常来回转赠) |
+
+### 3.4 转赠后接收方兑换积分明细
+
+> 以下为合法行为,资产转赠后归接收方所有,接收方有权兑换
+
+| 用户ID | 昵称 | 兑换笔数 | 兑换金额(元) | 性质 |
+|--------|------|---------|------------|------|
+| 9116 | 非洲人 | 30 | 10,737.00 | 合法 — 接收转赠后兑换 |
+| 9110 | 极品官方内部号 | 24 | 446.60 | 合法 |
+| 9305 | 新人 | 1 | 375.00 | 合法 |
+| 9209 | 程c | 9 | 220.00 | 合法 |
+| 9222 | 嗯?!!!! | 15 | 180.00 | 合法 |
+| 9336 | 有冰的帝君 | 1 | 60.00 | 合法 |
+| 9094 | 范巴斯滕救了一个美女 | 2 | 25.00 | 合法 |
+| 9210 | 非酋 | 3 | 22.50 | 合法 |
+| 9449 | 古利特使出了佛怒火莲 | 1 | 12.50 | 合法 |
+| 9248 | 不出last退了 | 3 | 8.60 | 合法 |
+| 9365 | 未命名 | 1 | 1.00 | 合法 |
+| 9230 | 巨欧小肥龙 | 1 | 0.60 | 合法 |
+| **合计** | | **91** | **12,088.80** | **全部合法** |
+
+### 3.5 多次转赠记录(并发 bug 产生的脏数据)
+
+| 资产ID | 转赠次数 | 路径 | 说明 |
+|--------|---------|------|------|
+| 42746 | 4 | 9336→9116 x4 | 同一操作并发触发4次 |
+| 46668 | 4 | 9210→9116 x4 | 同上 |
+| 43304 | 3 | 9305→9116, 9116→9305, 9305→9116 | 正常来回转赠 |
+| 44152 | 3 | 9248→9116 x3 | 并发触发3次 |
+| 46445 | 3 | 9230→9116 x3 | 并发触发3次 |
+| 46667 | 3 | 9210→9116 x3 | 并发触发3次 |
+| 51038 | 3 | 9210→9116, 9116→9210, 9210→9116 | 正常来回转赠 |
+| 其他 6 个 | 2 | — | 并发触发2次 |
+
+这些重复记录是脏数据,但未造成资产复制或积分重复。
+
+---
+
+## 四、修复状态
+
+| 修复项 | 状态 | Commit |
+|--------|------|--------|
+| SELECT FOR UPDATE 防并发转赠 | ✅ 已合并 main | `8229b41` |
+| RowsAffected 检查防静默失败 | ✅ 已合并 main | `8229b41` |
+| ~~禁止转赠资产兑换积分~~ | ❌ 已回退 | `749464c`,属业务策略非 bug 修复 |
+
+---
+
+## 五、结论
+
+1. **并发 bug 确实存在**:readDB 竞态 + RowsAffected 未检查,导致同一资产产生重复转赠记录和重复发货记录
+2. **实际经济损失为 0 元**:
+ - 没有任何资产被真正发了两份货(重复发货记录中,发送方一侧全部已取消)
+ - 没有任何资产被重复兑换积分
+ - 发送方没有在转赠后又兑换同一资产的积分
+3. **转赠后兑换积分是合法行为**:资产转赠后归接收方,接收方有权兑换
+4. **Bug 已修复**,防止未来可能的真正损失
diff --git a/exploit_report_20260311.txt b/exploit_report_20260311.txt
new file mode 100644
index 0000000..16f65c0
--- /dev/null
+++ b/exploit_report_20260311.txt
@@ -0,0 +1,1518 @@
+========================================================================================================================
+ 赠送资产薅积分漏洞 — 完整链路明细报告
+ 生成时间: 2026-03-11 16:10:40
+========================================================================================================================
+
+【一】涉及用户信息
+----------------------------------------------------------------------------------------------------
+ UID 昵称 手机号 状态 注册时间
+ ------------------------------------------------------------------------------------------
+ 9094 范巴斯滕救了一个美女 19382285440 正常 2026-01-19 07:13
+ 9110 极品官方内部号 19105657735 正常 2026-01-22 04:10
+ 9111 嘟嘟 18754515699 正常 2026-01-22 23:10
+ 9113 盖德·穆勒大力出奇迹 19164685626 正常 2026-01-23 03:13
+ 9116 非洲人 17381086073 正常 2026-01-23 04:54
+ 9117 小叶 18783929192 正常 2026-01-23 04:55
+ 9138 卷卷大魔王 15021159954 正常 2026-01-31 01:19
+ 9160 肖申克在武汉看电影 17331603630 正常 2026-02-03 14:59
+ 9199 欣喜的罗马里奥 18852772482 正常 2026-02-15 00:54
+ 9209 程c 13979106467 正常 2026-02-16 00:24
+ 9210 非酋 17303115993 正常 2026-02-16 00:26
+ 9222 嗯?!!!! 19275742612 正常 2026-02-16 11:14
+ 9230 巨欧小肥龙 15688032220 正常 2026-02-16 12:38
+ 9248 不出last退了 19874056809 正常 2026-02-16 22:27
+ 9280 诚心的肯尼 15243958112 正常 2026-02-17 02:04
+ 9305 新人 15200690367 正常 2026-02-17 20:21
+ 9330 拼搏的内马尔 13771103216 正常 2026-02-18 02:49
+ 9336 有冰的帝君 17708495187 正常 2026-02-18 21:40
+ 9347 约翰在武汉看电影 19527539116 正常 2026-02-19 00:34
+ 9359 雅典娜心花怒放 13829254006 正常 2026-02-19 17:40
+ 9365 未命名 18306540135 正常 2026-02-19 22:34
+ 9446 弗兰科望穿秋水 15957130050 正常 2026-03-03 10:25
+ 9449 古利特使出了佛怒火莲 18439413431 正常 2026-03-04 01:05
+
+
+【二】完整转赠链路明细(按时间排序)
+----------------------------------------------------------------------------------------------------------------------------------------------------------------
+ # 转赠时间 赠送方 接收方 资产ID 商品名称 价值(元) 状态 后续操作链路
+ -----------------------------------------------------------------------------------------------------------------------------------------------------------
+ 1 01-24 22:59:58 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30255 万代 HG GN-000 g.. 70.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 2 01-24 23:00:47 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30233 捏捏 1.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 3 01-24 23:01:29 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30241 SD随机款 40.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 4 01-24 23:07:27 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30256 模型改色马克笔7支 23.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 5 01-24 23:07:55 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30257 捏捏 1.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 6 01-24 23:21:20 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30264 麦当当 10.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 7 01-25 04:17:53 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30289 SD随机款 40.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 8 01-25 04:18:10 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30290 按压式金属丙烯马克笔1支 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 9 01-25 04:21:58 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30302 心动的王者假面绮宴主题马口铁.. 20.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 10 01-25 04:22:03 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30301 晨光水性笔 2.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 11 01-25 19:16:23 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30316 万代 HG 1/144 00.. 78.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 12 01-25 19:16:32 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 30317 小米巨能写中性笔0.5mm(.. 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 13 02-04 01:01:03 9110(极品官方内部号) 9160(肖申克在武汉看电..) 31938 摩动核 赤热 拼装幻赐 超可.. 175.00 已用 shipping_requested_via_share
+ 14 02-16 21:23:06 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 34111 晨光水性笔 2.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 15 02-16 21:23:12 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 34110 吧唧1个 1.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 16 02-16 21:23:16 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 34109 HG 风灵高达 88.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 17 02-17 11:38:39 9222(嗯?!!!!) 9116(非洲人) 37377 PG天使飞翼零式高达Wing.. 580.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → ✖兑换积分
+ 18 02-17 23:37:14 9280(诚心的肯尼) 9222(嗯?!!!!) 40389 柒匠 模型水性渗线液 高达模.. 15.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 19 02-17 23:37:47 9280(诚心的肯尼) 9222(嗯?!!!!) 40388 晨光水性笔 2.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 20 02-17 23:38:01 9280(诚心的肯尼) 9222(嗯?!!!!) 40390 PP夹1个 1.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 21 02-17 23:39:50 9280(诚心的肯尼) 9222(嗯?!!!!) 40391 模型改色马克笔7支 23.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 22 02-17 23:39:59 9280(诚心的肯尼) 9222(嗯?!!!!) 40393 柒匠 模型水性渗线液 高达模.. 15.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 23 02-17 23:40:06 9280(诚心的肯尼) 9222(嗯?!!!!) 40394 冰箱贴 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 24 02-17 23:40:12 9280(诚心的肯尼) 9222(嗯?!!!!) 40395 晨光水性笔 2.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 25 02-17 23:41:11 9280(诚心的肯尼) 9222(嗯?!!!!) 40392 模型改色马克笔7支 23.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 26 02-17 23:52:34 9110(极品官方内部号) 9222(嗯?!!!!) 40417 木质拼装模型积木蝴蝶折叠爪刀 6.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 27 02-17 23:52:39 9110(极品官方内部号) 9222(嗯?!!!!) 40416 麦当当 10.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 28 02-17 23:53:59 9209(程c) 9110(极品官方内部号) 40418 维达手帕纸1包 0.60 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 29 02-19 01:12:12 9347(约翰在武汉看电影) 9222(嗯?!!!!) 43226 尖头镊子1个 5.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 30 02-19 01:12:18 9347(约翰在武汉看电影) 9222(嗯?!!!!) 43225 高达电动小型打磨机器 16.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 31 02-19 01:12:23 9347(约翰在武汉看电影) 9222(嗯?!!!!) 43224 柒匠 模型水性渗线液 高达模.. 15.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 32 02-19 01:38:48 9347(约翰在武汉看电影) 9222(嗯?!!!!) 43291 万代 机动战士高达联名UVP.. 40.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 33 02-19 01:38:53 9347(约翰在武汉看电影) 9222(嗯?!!!!) 43292 冰箱贴 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 34 02-19 02:18:17 9305(新人) 9116(非洲人) 43304 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 35 02-19 02:24:28 9116(非洲人) 9305(新人) 43304 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 36 02-19 02:40:18 9305(新人) 9116(非洲人) 43304 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 37 02-19 02:53:03 9110(极品官方内部号) 9116(非洲人) 43423 HG 熊霸3 BEARGGU.. 79.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 38 02-19 13:26:50 9116(非洲人) 9248(不出last退了) 44155 冰箱贴 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 39 02-19 13:27:16 9116(非洲人) 9248(不出last退了) 44154 尖头镊子1个 5.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 40 02-20 22:13:58 9330(拼搏的内马尔) 9094(范巴斯滕救了一个..) 45366 三丽鸥保温杯公仔冰霸杯 88.90 已用 转赠 → 发货
+ 41 02-20 23:37:47 9110(极品官方内部号) 9365(未命名) 45408 捏捏 1.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 42 02-21 00:21:53 9209(程c) 9230(巨欧小肥龙) 45587 维达手帕纸1包 0.60 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 43 02-21 01:16:44 9116(非洲人) 9305(新人) 42761 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 44 02-21 14:53:09 9336(有冰的帝君) 9116(非洲人) 42746 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 45 02-21 14:54:33 9336(有冰的帝君) 9116(非洲人) 42746 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 46 02-21 14:54:56 9336(有冰的帝君) 9116(非洲人) 42746 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 47 02-21 14:55:34 9336(有冰的帝君) 9116(非洲人) 42746 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 48 02-21 14:58:16 9336(有冰的帝君) 9116(非洲人) 42757 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 49 02-21 15:00:46 9336(有冰的帝君) 9116(非洲人) 42758 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 50 02-21 15:04:28 9222(嗯?!!!!) 9116(非洲人) 45097 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 51 02-21 15:04:43 9222(嗯?!!!!) 9116(非洲人) 45098 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 52 02-21 15:05:04 9222(嗯?!!!!) 9116(非洲人) 45099 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 53 02-21 15:07:44 9222(嗯?!!!!) 9116(非洲人) 45100 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 54 02-21 15:09:10 9222(嗯?!!!!) 9116(非洲人) 46493 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 55 02-21 15:11:10 9222(嗯?!!!!) 9116(非洲人) 46494 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 56 02-21 15:12:36 9222(嗯?!!!!) 9116(非洲人) 46495 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 57 02-21 15:12:54 9222(嗯?!!!!) 9116(非洲人) 44285 万代 魂限 GFFMC PH.. 1450.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 58 02-21 16:43:08 9230(巨欧小肥龙) 9116(非洲人) 46445 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 59 02-21 16:43:17 9230(巨欧小肥龙) 9116(非洲人) 46445 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 60 02-21 16:43:37 9230(巨欧小肥龙) 9116(非洲人) 46445 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 61 02-21 16:44:28 9230(巨欧小肥龙) 9116(非洲人) 46446 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 62 02-21 16:47:04 9230(巨欧小肥龙) 9116(非洲人) 46447 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 63 02-21 16:49:56 9209(程c) 9116(非洲人) 46506 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 64 02-21 16:50:09 9209(程c) 9116(非洲人) 46506 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → ✖兑换积分
+ 65 02-21 16:50:58 9209(程c) 9116(非洲人) 46507 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 66 02-21 16:51:25 9209(程c) 9116(非洲人) 46508 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 67 02-21 16:52:06 9209(程c) 9116(非洲人) 46509 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 68 02-21 23:49:13 9210(非酋) 9116(非洲人) 44115 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 69 02-21 23:49:40 9210(非酋) 9116(非洲人) 46665 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 70 02-21 23:49:50 9210(非酋) 9116(非洲人) 46666 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 71 02-21 23:49:58 9210(非酋) 9116(非洲人) 46666 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 72 02-21 23:50:06 9210(非酋) 9116(非洲人) 46667 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 73 02-21 23:50:12 9210(非酋) 9116(非洲人) 46667 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 74 02-21 23:50:20 9210(非酋) 9116(非洲人) 46668 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 75 02-21 23:50:28 9210(非酋) 9116(非洲人) 46668 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 76 02-21 23:50:35 9210(非酋) 9116(非洲人) 46668 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 77 02-21 23:51:11 9210(非酋) 9116(非洲人) 46668 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 78 02-21 23:51:31 9210(非酋) 9116(非洲人) 46667 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 79 02-21 23:51:43 9210(非酋) 9116(非洲人) 46669 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 80 02-21 23:51:51 9210(非酋) 9116(非洲人) 46669 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 81 02-21 23:52:12 9210(非酋) 9116(非洲人) 46670 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 82 02-21 23:52:25 9210(非酋) 9116(非洲人) 46671 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 83 02-21 23:52:46 9210(非酋) 9116(非洲人) 46672 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 84 02-21 23:53:04 9210(非酋) 9116(非洲人) 46673 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 85 02-21 23:53:11 9210(非酋) 9116(非洲人) 46672 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 86 02-21 23:53:24 9210(非酋) 9116(非洲人) 46673 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 87 02-21 23:53:36 9210(非酋) 9116(非洲人) 46674 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 88 02-21 23:53:51 9210(非酋) 9116(非洲人) 46675 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 89 02-21 23:54:15 9210(非酋) 9116(非洲人) 46676 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 90 02-22 00:02:31 9210(非酋) 9116(非洲人) 46677 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 91 02-22 00:02:51 9210(非酋) 9116(非洲人) 46678 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 92 02-22 00:03:14 9210(非酋) 9116(非洲人) 46679 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 93 02-22 00:03:43 9210(非酋) 9116(非洲人) 46681 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 94 02-22 00:04:06 9210(非酋) 9116(非洲人) 46682 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 95 02-22 00:04:51 9210(非酋) 9116(非洲人) 46683 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 96 02-22 00:05:25 9210(非酋) 9116(非洲人) 46684 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 97 02-22 00:05:52 9210(非酋) 9116(非洲人) 46685 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 98 02-22 00:06:17 9210(非酋) 9116(非洲人) 46686 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 99 02-22 00:06:30 9210(非酋) 9116(非洲人) 46686 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 100 02-22 00:06:43 9210(非酋) 9116(非洲人) 46687 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 101 02-22 00:07:03 9210(非酋) 9116(非洲人) 46688 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 102 02-22 00:07:23 9210(非酋) 9116(非洲人) 46689 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 103 02-22 00:07:44 9210(非酋) 9116(非洲人) 46690 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 104 02-22 00:08:04 9210(非酋) 9116(非洲人) 46691 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 105 02-22 23:46:20 9248(不出last退了) 9116(非洲人) 44150 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 106 02-22 23:46:50 9248(不出last退了) 9116(非洲人) 44151 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 107 02-22 23:47:03 9248(不出last退了) 9116(非洲人) 44152 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 108 02-22 23:47:10 9248(不出last退了) 9116(非洲人) 44152 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 109 02-22 23:47:23 9248(不出last退了) 9116(非洲人) 44152 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → 取消发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 110 02-22 23:47:49 9248(不出last退了) 9116(非洲人) 44153 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 111 02-23 19:39:36 9116(非洲人) 9210(非酋) 47297 兰博基尼乐高积木益智拼装模型 12.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 112 02-23 20:17:10 9116(非洲人) 9210(非酋) 47299 木质拼装模型积木蝴蝶折叠爪刀 6.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 113 02-23 20:18:01 9210(非酋) 9116(非洲人) 47249 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 114 02-23 20:18:33 9210(非酋) 9116(非洲人) 47298 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 115 02-23 20:19:07 9210(非酋) 9116(非洲人) 47300 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 116 02-24 01:23:17 9336(有冰的帝君) 9110(极品官方内部号) 47721 藏道模型 创神天未 天未动漫 295.00 已用 转赠 → 发货
+ 117 02-24 21:22:46 9209(程c) 9210(非酋) 47927 高达贴纸(10张) 4.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 118 02-25 18:06:37 9336(有冰的帝君) 9110(极品官方内部号) 48197 打磨工具五件套 15.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 119 02-25 18:08:55 9116(非洲人) 9110(极品官方内部号) 48198 得力NS755纽赛臻干净橡皮.. 2.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 120 02-25 18:28:25 9116(非洲人) 9110(极品官方内部号) 48203 冰箱贴 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 121 02-25 18:30:53 9116(非洲人) 9110(极品官方内部号) 48204 冰箱贴 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 122 02-25 18:32:59 9116(非洲人) 9110(极品官方内部号) 48206 晨光水性笔 2.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 123 02-26 03:02:50 9209(程c) 9110(极品官方内部号) 48309 晨光水性笔 2.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 124 02-26 16:02:33 9222(嗯?!!!!) 9347(约翰在武汉看电影) 48207 摩动核魔神四将魔礼青合金骨架 420.00 已用 转赠 → 发货
+ 125 02-27 14:31:46 9116(非洲人) 9209(程c) 49166 王者旅行日记吊坠 21.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 126 02-27 17:51:23 9330(拼搏的内马尔) 9094(范巴斯滕救了一个..) 45343 兰博基尼乐高积木益智拼装模型 12.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 127 02-27 18:01:22 9330(拼搏的内马尔) 9094(范巴斯滕救了一个..) 49120 兰博基尼乐高积木益智拼装模型 12.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 128 02-28 01:25:41 9230(巨欧小肥龙) 9209(程c) 49296 聚匠模型柯西HG1/144国.. 120.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 129 02-28 01:25:48 9230(巨欧小肥龙) 9209(程c) 49295 高达贴纸(10张) 4.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 130 02-28 01:46:26 9210(非酋) 9209(程c) 49303 按压式金属丙烯马克笔1支 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 131 02-28 01:46:39 9210(非酋) 9209(程c) 49304 按压式金属丙烯马克笔1支 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 132 02-28 01:48:12 9210(非酋) 9209(程c) 49305 按压式金属丙烯马克笔1支 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 133 02-28 01:48:21 9210(非酋) 9209(程c) 49306 按压式金属丙烯马克笔1支 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 134 02-28 02:09:30 9110(极品官方内部号) 9209(程c) 49318 按压式金属丙烯马克笔1支 3.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 135 02-28 02:09:35 9110(极品官方内部号) 9209(程c) 49317 SD BB战士非凡强袭自由高.. 60.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 136 02-28 20:00:59 9336(有冰的帝君) 9110(极品官方内部号) 49508 万达PG菲尼克斯 NT 1/.. 3400.00 已用 转赠 → 发货
+ 137 02-28 20:15:05 9305(新人) 9116(非洲人) 47096 万代PG 双O莱泽器 900.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 138 03-01 00:04:28 9248(不出last退了) 9116(非洲人) 49426 万代MB海盗X1高达拼凑型 .. 1315.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 139 03-02 12:52:23 9210(非酋) 9116(非洲人) 51038 PB限定 MG 红龙形态红龙.. 605.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 140 03-02 14:06:18 9116(非洲人) 9210(非酋) 51038 PB限定 MG 红龙形态红龙.. 605.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 141 03-02 23:11:37 9138(卷卷大魔王) 9116(非洲人) 51316 万代PG MK2奥古配色 .. 1430.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 142 03-02 23:11:47 9138(卷卷大魔王) 9116(非洲人) 51311 pgu1/60RX78元祖2.. 1700.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 143 03-03 00:04:28 9210(非酋) 9116(非洲人) 51038 PB限定 MG 红龙形态红龙.. 605.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 144 03-03 00:04:35 9210(非酋) 9116(非洲人) 51358 摩动核 拼装吕布 合金骨架拼.. 460.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested → 取消发货 → batch_shipping_requested
+ 145 03-03 00:42:07 9111(嘟嘟) 9336(有冰的帝君) 51418 SD BB战士非凡强袭自由高.. 60.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 146 03-03 02:32:09 9117(小叶) 9116(非洲人) 51590 PP夹1个 1.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 147 03-03 02:32:28 9117(小叶) 9116(非洲人) 51591 PP夹1个 1.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 148 03-03 11:03:13 9336(有冰的帝君) 9446(弗兰科望穿秋水) 52094 美佳龙MJL原装单刃水口钳龙.. 29.00 已用 转赠 → 发货
+ 149 03-03 11:27:42 9111(嘟嘟) 9210(非酋) 52104 长龙再版7701黑强袭自由带.. 320.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 150 03-03 12:14:43 9359(雅典娜心花怒放) 9248(不出last退了) 48196 维达手帕纸1包 0.60 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 151 03-04 02:36:58 9336(有冰的帝君) 9116(非洲人) 52406 模寿 至臻 空呪 空况罗 国.. 700.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 152 03-04 22:34:54 9094(范巴斯滕救了一个..) 9449(古利特使出了佛怒..) 52338 兰博基尼乐高积木益智拼装模型 12.50 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 153 03-05 19:40:40 9199(欣喜的罗马里奥) 9116(非洲人) 46467 雷霆魔鬼鱼 无限新星 IN .. 308.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 154 03-05 19:40:49 9199(欣喜的罗马里奥) 9116(非洲人) 47719 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 155 03-05 19:41:23 9199(欣喜的罗马里奥) 9116(非洲人) 47720 MG 牛高达VER.KA 卡.. 375.00 已用 转赠 → 发货 → 取消发货 → batch_shipping_requested
+ 156 03-05 22:21:39 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 53361 绿扎古Q版-SDCS 18.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+ 157 03-05 22:21:56 9113(盖德·穆勒大力出..) 9110(极品官方内部号) 53362 绿扎古Q版-SDCS 18.00 已用 转赠 → 发货 → 取消发货 → ✖兑换积分
+
+ 共 157 条转赠记录
+
+
+【三】转赠资产的发货/取消发货记录
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+
+【四】薅取积分入账明细
+------------------------------------------------------------------------------------------------------------------------
+ 流水ID 用户ID 昵称 入账积分 类型 关联信息 入账时间
+ -------------------------------------------------------------------------------------------------------------------
+ 5203 9094 范巴斯滕救了一个美女 3000 redeem_reward batch_redeem_8_items 01-28 23:57:11
+ 5204 9094 范巴斯滕救了一个美女 500 redeem_reward batch_redeem_1_items 01-28 23:57:15
+ 5358 9094 范巴斯滕救了一个美女 1800 redeem_reward batch_redeem_4_items 02-02 01:20:09
+ 5553 9094 范巴斯滕救了一个美女 5800 redeem_reward batch_redeem_5_items 02-14 20:41:43
+ 5612 9094 范巴斯滕救了一个美女 1700 redeem_reward batch_redeem_5_items 02-15 22:55:30
+ 6743 9094 范巴斯滕救了一个美女 2300 redeem_reward batch_redeem_7_items 02-18 21:15:49
+ 6745 9094 范巴斯滕救了一个美女 600 redeem_reward batch_redeem_2_items 02-18 21:32:50
+ 7172 9094 范巴斯滕救了一个美女 800 redeem_reward batch_redeem_2_items 02-20 22:14:34
+ 7604 9094 范巴斯滕救了一个美女 300 redeem_reward batch_redeem_1_items 02-22 02:45:33
+ 7628 9094 范巴斯滕救了一个美女 2000 redeem_reward batch_redeem_6_items 02-22 20:19:58
+ 7660 9094 范巴斯滕救了一个美女 300 redeem_reward batch_redeem_1_items 02-23 01:34:48
+ 7749 9094 范巴斯滕救了一个美女 1100 redeem_reward batch_redeem_3_items 02-23 22:57:08
+ 7751 9094 范巴斯滕救了一个美女 600 redeem_reward batch_redeem_2_items 02-23 23:37:14
+ 7753 9094 范巴斯滕救了一个美女 300 redeem_reward batch_redeem_5_items 02-23 23:39:18
+ 8004 9094 范巴斯滕救了一个美女 3500 redeem_reward batch_redeem_9_items 02-26 22:33:24
+ 8049 9094 范巴斯滕救了一个美女 2500 redeem_reward batch_redeem_2_items 02-27 18:01:41
+ 8070 9094 范巴斯滕救了一个美女 1100 redeem_reward batch_redeem_3_items 02-27 21:01:16
+ 8192 9094 范巴斯滕救了一个美女 1000 redeem_reward batch_redeem_1_items 03-01 02:04:47
+ 8193 9094 范巴斯滕救了一个美女 1000 redeem_reward batch_redeem_1_items 03-01 02:08:18
+ 8240 9094 范巴斯滕救了一个美女 800 redeem_reward batch_redeem_2_items 03-01 22:05:34
+ 8333 9094 范巴斯滕救了一个美女 900 redeem_reward batch_redeem_2_items 03-02 21:38:40
+ 8488 9094 范巴斯滕救了一个美女 700 redeem_reward batch_redeem_2_items 03-03 02:47:03
+ 8569 9094 范巴斯滕救了一个美女 1600 redeem_reward batch_redeem_3_items 03-04 01:28:18
+ 8649 9094 范巴斯滕救了一个美女 2100 redeem_reward batch_redeem_2_items 03-04 20:27:33
+ 8666 9094 范巴斯滕救了一个美女 1000 redeem_reward batch_redeem_1_items 03-04 21:18:10
+ 8675 9094 范巴斯滕救了一个美女 600 redeem_reward batch_redeem_2_items 03-04 22:13:46
+ 8763 9094 范巴斯滕救了一个美女 700 redeem_reward batch_redeem_2_items 03-05 01:37:49
+ 8764 9094 范巴斯滕救了一个美女 300 redeem_reward batch_redeem_5_items 03-05 01:39:12
+ 8812 9094 范巴斯滕救了一个美女 600 redeem_reward batch_redeem_2_items 03-05 20:57:11
+ 8851 9094 范巴斯滕救了一个美女 3000 redeem_reward batch_redeem_8_items 03-06 00:05:23
+ 8853 9094 范巴斯滕救了一个美女 960 redeem_reward batch_redeem_3_items 03-06 02:22:29
+ 8854 9094 范巴斯滕救了一个美女 1400 redeem_reward batch_redeem_9_items 03-06 02:25:45
+ 用户 9094 小计: 44860 积分 (448.60 元)
+
+ 4945 9110 极品官方内部号 71700 redeem_reward batch_redeem_127_items 01-22 05:04:45
+ 4946 9110 极品官方内部号 9600 redeem_reward batch_redeem_30_items 01-22 05:12:50
+ 4947 9110 极品官方内部号 2900 redeem_reward batch_redeem_11_items 01-22 05:13:31
+ 4948 9110 极品官方内部号 9100 redeem_reward batch_redeem_16_items 01-22 05:16:10
+ 4949 9110 极品官方内部号 7200 redeem_reward batch_redeem_19_items 01-22 05:19:08
+ 4950 9110 极品官方内部号 2150 redeem_reward batch_redeem_10_items 01-22 05:19:55
+ 4951 9110 极品官方内部号 3600 redeem_reward batch_redeem_7_items 01-22 05:22:43
+ 4952 9110 极品官方内部号 300 redeem_reward batch_redeem_3_items 01-22 05:27:40
+ 4953 9110 极品官方内部号 5600 redeem_reward batch_redeem_40_items 01-22 05:28:33
+ 4954 9110 极品官方内部号 8200 redeem_reward batch_redeem_30_items 01-22 05:29:27
+ 4955 9110 极品官方内部号 3000 redeem_reward batch_redeem_1_items 01-22 05:33:05
+ 4956 9110 极品官方内部号 2550 redeem_reward batch_redeem_10_items 01-22 05:34:39
+ 4957 9110 极品官方内部号 6250 redeem_reward batch_redeem_10_items 01-22 05:35:19
+ 4958 9110 极品官方内部号 3600 redeem_reward batch_redeem_28_items 01-22 05:37:08
+ 4959 9110 极品官方内部号 2400 redeem_reward batch_redeem_4_items 01-22 05:39:23
+ 4960 9110 极品官方内部号 5000 redeem_reward batch_redeem_1_items 01-22 05:40:35
+ 4961 9110 极品官方内部号 2100 redeem_reward batch_redeem_1_items 01-22 05:42:10
+ 4962 9110 极品官方内部号 1400 redeem_reward batch_redeem_2_items 01-22 05:54:54
+ 4964 9110 极品官方内部号 1000 redeem_reward batch_redeem_1_items 01-22 09:20:46
+ 4971 9110 极品官方内部号 150 redeem_reward batch_redeem_1_items 01-22 18:36:48
+ 4974 9110 极品官方内部号 3200 redeem_reward batch_redeem_6_items 01-22 23:25:44
+ 4975 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 01-22 23:26:37
+ 4976 9110 极品官方内部号 2400 redeem_reward batch_redeem_10_items 01-22 23:27:11
+ 4977 9110 极品官方内部号 3000 redeem_reward batch_redeem_1_items 01-23 00:41:43
+ 4978 9110 极品官方内部号 6600 redeem_reward batch_redeem_5_items 01-23 00:46:52
+ 4979 9110 极品官方内部号 5400 redeem_reward batch_redeem_5_items 01-23 01:07:11
+ 4980 9110 极品官方内部号 700 redeem_reward batch_redeem_2_items 01-23 01:18:13
+ 4982 9110 极品官方内部号 600 redeem_reward batch_redeem_2_items 01-23 01:20:05
+ 4983 9110 极品官方内部号 16000 redeem_reward batch_redeem_1_items 01-23 01:21:54
+ 4994 9110 极品官方内部号 500 redeem_reward batch_redeem_2_items 01-23 02:21:28
+ 4995 9110 极品官方内部号 700 redeem_reward batch_redeem_2_items 01-23 02:25:08
+ 4997 9110 极品官方内部号 2550 redeem_reward batch_redeem_5_items 01-23 04:03:10
+ 4998 9110 极品官方内部号 500 redeem_reward batch_redeem_1_items 01-23 04:03:46
+ 4999 9110 极品官方内部号 1000 redeem_reward batch_redeem_1_items 01-23 04:16:11
+ 5000 9110 极品官方内部号 100 redeem_reward batch_redeem_1_items 01-23 04:18:08
+ 5001 9110 极品官方内部号 100 redeem_reward batch_redeem_1_items 01-23 04:18:32
+ 5002 9110 极品官方内部号 33000 redeem_reward batch_redeem_1_items 01-23 04:44:58
+ 5003 9110 极品官方内部号 150 redeem_reward batch_redeem_1_items 01-23 04:45:17
+ 5013 9110 极品官方内部号 600 redeem_reward batch_redeem_1_items 01-23 05:39:39
+ 5014 9110 极品官方内部号 800 redeem_reward batch_redeem_1_items 01-23 05:43:44
+ 5015 9110 极品官方内部号 2100 redeem_reward batch_redeem_1_items 01-23 05:45:05
+ 5019 9110 极品官方内部号 800 redeem_reward batch_redeem_1_items 01-23 22:24:00
+ 5020 9110 极品官方内部号 1500 redeem_reward batch_redeem_1_items 01-23 22:24:49
+ 5021 9110 极品官方内部号 600 redeem_reward batch_redeem_1_items 01-23 22:25:45
+ 5022 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 01-24 00:45:02
+ 5023 9110 极品官方内部号 1300 redeem_reward batch_redeem_3_items 01-24 00:59:12
+ 5024 9110 极品官方内部号 11000 redeem_reward batch_redeem_1_items 01-24 01:53:00
+ 5027 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 01-24 02:55:36
+ 5030 9110 极品官方内部号 2500 redeem_reward batch_redeem_6_items 01-24 22:22:10
+ 5031 9110 极品官方内部号 15100 redeem_reward batch_redeem_4_items 01-24 23:05:03
+ 5035 9110 极品官方内部号 2400 redeem_reward batch_redeem_2_items 01-24 23:08:05
+ 5038 9110 极品官方内部号 1000 redeem_reward batch_redeem_1_items 01-24 23:21:28
+ 5050 9110 极品官方内部号 12300 redeem_reward batch_redeem_4_items 01-25 04:18:28
+ 5054 9110 极品官方内部号 2200 redeem_reward batch_redeem_2_items 01-25 04:22:17
+ 5055 9110 极品官方内部号 500 redeem_reward batch_redeem_1_items 01-25 04:31:03
+ 5056 9110 极品官方内部号 100 redeem_reward batch_redeem_1_items 01-25 04:32:11
+ 5061 9110 极品官方内部号 24100 redeem_reward batch_redeem_3_items 01-25 19:16:59
+ 5062 9110 极品官方内部号 4000 redeem_reward batch_redeem_1_items 01-25 19:28:11
+ 5063 9110 极品官方内部号 1250 redeem_reward batch_redeem_1_items 01-25 19:29:16
+ 5064 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 01-25 19:29:40
+ 5072 9110 极品官方内部号 3300 redeem_reward batch_redeem_1_items 01-25 20:19:21
+ 5084 9110 极品官方内部号 4850 redeem_reward batch_redeem_8_items 01-25 20:22:54
+ 5096 9110 极品官方内部号 3300 redeem_reward batch_redeem_10_items 01-25 20:26:51
+ 5107 9110 极品官方内部号 6000 redeem_reward batch_redeem_10_items 01-25 20:32:57
+ 5109 9110 极品官方内部号 1600 redeem_reward batch_redeem_2_items 01-25 20:34:32
+ 5230 9110 极品官方内部号 1400 redeem_reward batch_redeem_4_items 01-29 12:54:14
+ 5413 9110 极品官方内部号 1000 redeem_reward batch_redeem_1_items 02-03 14:28:09
+ 5415 9110 极品官方内部号 1200 redeem_reward batch_redeem_4_items 02-03 15:59:27
+ 5416 9110 极品官方内部号 2000 redeem_reward batch_redeem_12_items 02-03 16:01:06
+ 5417 9110 极品官方内部号 1000 redeem_reward batch_redeem_10_items 02-03 16:05:45
+ 5418 9110 极品官方内部号 2400 redeem_reward batch_redeem_10_items 02-03 16:08:23
+ 5419 9110 极品官方内部号 1400 redeem_reward batch_redeem_10_items 02-03 16:08:39
+ 5420 9110 极品官方内部号 1400 redeem_reward batch_redeem_10_items 02-03 16:08:57
+ 5421 9110 极品官方内部号 1000 redeem_reward batch_redeem_10_items 02-03 16:09:15
+ 5422 9110 极品官方内部号 1000 redeem_reward batch_redeem_10_items 02-03 16:09:34
+ 5423 9110 极品官方内部号 1000 redeem_reward batch_redeem_10_items 02-03 16:09:57
+ 5424 9110 极品官方内部号 300 redeem_reward batch_redeem_3_items 02-03 16:10:20
+ 5729 9110 极品官方内部号 17000 redeem_reward batch_redeem_22_items 02-16 20:50:11
+ 5730 9110 极品官方内部号 19000 redeem_reward batch_redeem_9_items 02-16 20:50:18
+ 5747 9110 极品官方内部号 42390 redeem_reward batch_redeem_8_items 02-16 21:23:43
+ 5961 9110 极品官方内部号 16900 redeem_reward batch_redeem_72_items 02-17 01:45:37
+ 6366 9110 极品官方内部号 1500 redeem_reward batch_redeem_17_items 02-17 23:29:09
+ 6394 9110 极品官方内部号 60 redeem_reward batch_redeem_1_items 02-17 23:54:11
+ 6528 9110 极品官方内部号 900 redeem_reward batch_redeem_9_items 02-18 16:53:10
+ 6533 9110 极品官方内部号 360 redeem_reward batch_redeem_6_items 02-18 16:54:24
+ 6825 9110 极品官方内部号 7200 redeem_reward batch_redeem_1_items 02-19 01:44:36
+ 7165 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 02-20 21:23:44
+ 7597 9110 极品官方内部号 3000 redeem_reward batch_redeem_2_items 02-22 00:50:46
+ 7598 9110 极品官方内部号 500 redeem_reward batch_redeem_1_items 02-22 00:51:43
+ 7599 9110 极品官方内部号 2500 redeem_reward batch_redeem_1_items 02-22 00:52:44
+ 7600 9110 极品官方内部号 2800 redeem_reward batch_redeem_5_items 02-22 00:55:30
+ 7635 9110 极品官方内部号 1600 redeem_reward batch_redeem_5_items 02-22 20:46:22
+ 7636 9110 极品官方内部号 2500 redeem_reward batch_redeem_2_items 02-22 20:47:04
+ 7637 9110 极品官方内部号 800 redeem_reward batch_redeem_1_items 02-22 20:48:06
+ 7639 9110 极品官方内部号 13200 redeem_reward batch_redeem_8_items 02-22 20:53:03
+ 7780 9110 极品官方内部号 4000 redeem_reward batch_redeem_1_items 02-24 02:47:38
+ 7781 9110 极品官方内部号 400 redeem_reward batch_redeem_1_items 02-24 03:20:45
+ 7784 9110 极品官方内部号 1600 redeem_reward batch_redeem_2_items 02-24 03:25:52
+ 7825 9110 极品官方内部号 400 redeem_reward batch_redeem_1_items 02-24 21:19:55
+ 7873 9110 极品官方内部号 1500 redeem_reward batch_redeem_1_items 02-25 18:06:56
+ 7875 9110 极品官方内部号 250 redeem_reward batch_redeem_1_items 02-25 18:09:12
+ 7880 9110 极品官方内部号 240 redeem_reward batch_redeem_4_items 02-25 18:26:55
+ 7883 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 02-25 18:29:03
+ 7884 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 02-25 18:31:08
+ 7887 9110 极品官方内部号 200 redeem_reward batch_redeem_1_items 02-25 18:33:06
+ 8084 9110 极品官方内部号 800 redeem_reward batch_redeem_3_items 02-28 00:14:30
+ 8086 9110 极品官方内部号 27000 redeem_reward batch_redeem_2_items 02-28 00:23:03
+ 8088 9110 极品官方内部号 21600 redeem_reward batch_redeem_2_items 02-28 00:45:44
+ 8188 9110 极品官方内部号 1000 redeem_reward batch_redeem_2_items 03-01 01:01:39
+ 8194 9110 极品官方内部号 16900 redeem_reward batch_redeem_4_items 03-01 02:10:32
+ 8268 9110 极品官方内部号 5600 redeem_reward batch_redeem_4_items 03-02 00:36:22
+ 8365 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 03-02 22:46:07
+ 8690 9110 极品官方内部号 40800 redeem_reward batch_redeem_9_items 03-04 22:28:26
+ 8751 9110 极品官方内部号 26300 redeem_reward batch_redeem_10_items 03-05 00:14:02
+ 8766 9110 极品官方内部号 23000 redeem_reward batch_redeem_1_items 03-05 01:55:59
+ 8799 9110 极品官方内部号 600 redeem_reward batch_redeem_2_items 03-05 10:01:07
+ 8813 9110 极品官方内部号 5000 redeem_reward batch_redeem_4_items 03-05 21:01:20
+ 8814 9110 极品官方内部号 1300 redeem_reward batch_redeem_2_items 03-05 21:02:40
+ 8837 9110 极品官方内部号 15400 redeem_reward batch_redeem_4_items 03-05 22:18:24
+ 8838 9110 极品官方内部号 3600 redeem_reward batch_redeem_2_items 03-05 22:22:12
+ 8875 9110 极品官方内部号 300 redeem_reward batch_redeem_1_items 03-06 07:45:13
+ 8877 9110 极品官方内部号 100 redeem_reward batch_redeem_1_items 03-06 09:01:29
+ 8910 9110 极品官方内部号 2800 redeem_reward batch_redeem_5_items 03-07 15:13:49
+ 8915 9110 极品官方内部号 8400 redeem_reward batch_redeem_3_items 03-07 15:16:00
+ 8934 9110 极品官方内部号 1000 redeem_reward batch_redeem_2_items 03-07 21:13:48
+ 8936 9110 极品官方内部号 2700 redeem_reward batch_redeem_4_items 03-07 21:16:23
+ 8938 9110 极品官方内部号 2300 redeem_reward batch_redeem_4_items 03-07 21:17:59
+ 8940 9110 极品官方内部号 2000 redeem_reward batch_redeem_4_items 03-07 21:20:33
+ 8942 9110 极品官方内部号 1300 redeem_reward batch_redeem_4_items 03-07 21:22:44
+ 用户 9110 小计: 695600 积分 (6956.00 元)
+
+ 5005 9116 非洲人 1300 redeem_reward batch_redeem_4_items 01-23 05:03:12
+ 5006 9116 非洲人 1100 redeem_reward batch_redeem_2_items 01-23 05:06:42
+ 5008 9116 非洲人 600 redeem_reward batch_redeem_1_items 01-23 05:08:08
+ 5011 9116 非洲人 3700 redeem_reward batch_redeem_3_items 01-23 05:12:51
+ 5065 9116 非洲人 3440 redeem_reward batch_redeem_2_items 01-25 20:07:40
+ 5066 9116 非洲人 5000 redeem_reward batch_redeem_5_items 01-25 20:14:31
+ 5068 9116 非洲人 600 redeem_reward batch_redeem_1_items 01-25 20:17:55
+ 5070 9116 非洲人 600 redeem_reward batch_redeem_1_items 01-25 20:18:53
+ 5074 9116 非洲人 600 redeem_reward batch_redeem_1_items 01-25 20:19:36
+ 5078 9116 非洲人 8900 redeem_reward batch_redeem_1_items 01-25 20:20:48
+ 5095 9116 非洲人 1000 redeem_reward batch_redeem_1_items 01-25 20:26:09
+ 5776 9116 非洲人 600 redeem_reward batch_redeem_2_items 02-16 22:17:21
+ 5778 9116 非洲人 300 redeem_reward batch_redeem_1_items 02-16 22:18:02
+ 5780 9116 非洲人 400 redeem_reward batch_redeem_1_items 02-16 22:18:56
+ 5782 9116 非洲人 400 redeem_reward batch_redeem_1_items 02-16 22:19:39
+ 5785 9116 非洲人 300 redeem_reward batch_redeem_1_items 02-16 22:21:09
+ 6213 9116 非洲人 550 redeem_reward batch_redeem_3_items 02-17 17:53:39
+ 6215 9116 非洲人 10300 redeem_reward batch_redeem_10_items 02-17 18:04:46
+ 6219 9116 非洲人 1600 redeem_reward batch_redeem_8_items 02-17 18:10:42
+ 6222 9116 非洲人 10800 redeem_reward batch_redeem_11_items 02-17 18:15:36
+ 6223 9116 非洲人 3300 redeem_reward batch_redeem_10_items 02-17 18:18:04
+ 6225 9116 非洲人 3000 redeem_reward batch_redeem_10_items 02-17 18:23:28
+ 6229 9116 非洲人 240 redeem_reward batch_redeem_4_items 02-17 18:28:10
+ 6277 9116 非洲人 1500 redeem_reward batch_redeem_1_items 02-17 20:10:08
+ 6485 9116 非洲人 300 redeem_reward batch_redeem_5_items 02-18 11:18:05
+ 6512 9116 非洲人 200 redeem_reward batch_redeem_2_items 02-18 16:44:40
+ 6536 9116 非洲人 200 redeem_reward batch_redeem_2_items 02-18 16:57:30
+ 6593 9116 非洲人 3300 redeem_reward batch_redeem_11_items 02-18 17:34:57
+ 6595 9116 非洲人 3000 redeem_reward batch_redeem_10_items 02-18 17:35:45
+ 6603 9116 非洲人 1800 redeem_reward batch_redeem_30_items 02-18 17:47:22
+ 6606 9116 非洲人 600 redeem_reward batch_redeem_10_items 02-18 17:47:43
+ 6608 9116 非洲人 1200 redeem_reward batch_redeem_20_items 02-18 17:48:16
+ 6610 9116 非洲人 600 redeem_reward batch_redeem_10_items 02-18 17:48:33
+ 6612 9116 非洲人 600 redeem_reward batch_redeem_10_items 02-18 17:48:51
+ 6704 9116 非洲人 3660 redeem_reward batch_redeem_12_items 02-18 18:18:07
+ 6729 9116 非洲人 300 redeem_reward batch_redeem_5_items 02-18 19:25:41
+ 6751 9116 非洲人 300 redeem_reward batch_redeem_1_items 02-18 22:12:46
+ 6754 9116 非洲人 900 redeem_reward batch_redeem_15_items 02-18 22:30:19
+ 6775 9116 非洲人 33240 redeem_reward batch_redeem_5_items 02-18 23:15:35
+ 6815 9116 非洲人 7400 redeem_reward batch_redeem_4_items 02-19 01:32:23
+ 6845 9116 非洲人 37740 redeem_reward batch_redeem_5_items 02-19 02:42:09
+ 6858 9116 非洲人 7900 redeem_reward batch_redeem_1_items 02-19 02:53:20
+ 6879 9116 非洲人 960 redeem_reward batch_redeem_10_items 02-19 03:07:53
+ 6880 9116 非洲人 60 redeem_reward batch_redeem_1_items 02-19 03:15:08
+ 6884 9116 非洲人 1650 redeem_reward batch_redeem_10_items 02-19 03:17:41
+ 6894 9116 非洲人 120 redeem_reward batch_redeem_2_items 02-19 03:26:40
+ 6966 9116 非洲人 1140 redeem_reward batch_redeem_19_items 02-19 15:00:14
+ 6967 9116 非洲人 60 redeem_reward batch_redeem_1_items 02-19 15:00:17
+ 6992 9116 非洲人 2000 redeem_reward batch_redeem_4_items 02-19 18:18:55
+ 7023 9116 非洲人 300 redeem_reward batch_redeem_5_items 02-19 18:45:33
+ 7026 9116 非洲人 600 redeem_reward batch_redeem_10_items 02-19 18:47:18
+ 7150 9116 非洲人 300 redeem_reward batch_redeem_1_items 02-20 20:27:10
+ 7330 9116 非洲人 139000 redeem_reward batch_redeem_5_items 02-21 01:39:30
+ 7449 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 14:56:14
+ 7450 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 14:58:24
+ 7451 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 15:00:57
+ 7452 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 15:04:38
+ 7453 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 15:04:50
+ 7454 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 15:05:54
+ 7455 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 15:07:50
+ 7456 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 15:09:16
+ 7457 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 15:11:17
+ 7458 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 15:12:43
+ 7474 9116 非洲人 412500 redeem_reward batch_redeem_11_items 02-21 16:43:43
+ 7475 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 16:44:33
+ 7476 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 16:47:13
+ 7477 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 16:50:15
+ 7478 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 16:51:03
+ 7479 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 16:51:31
+ 7480 9116 非洲人 37500 redeem_reward batch_redeem_1_items 02-21 16:52:12
+ 7645 9116 非洲人 2790 redeem_reward batch_redeem_3_items 02-22 21:52:59
+ 7710 9116 非洲人 120 redeem_reward batch_redeem_2_items 02-23 18:03:07
+ 7995 9116 非洲人 450 redeem_reward batch_redeem_2_items 02-26 22:03:02
+ 7996 9116 非洲人 300 redeem_reward batch_redeem_1_items 02-26 22:04:20
+ 7998 9116 非洲人 600 redeem_reward batch_redeem_10_items 02-26 22:04:49
+ 8005 9116 非洲人 400 redeem_reward batch_redeem_1_items 02-26 22:34:56
+ 8044 9116 非洲人 1250 redeem_reward batch_redeem_1_items 02-27 14:30:54
+ 8082 9116 非洲人 300 redeem_reward batch_redeem_1_items 02-28 00:01:15
+ 8102 9116 非洲人 900 redeem_reward batch_redeem_3_items 02-28 01:53:40
+ 8231 9116 非洲人 300 redeem_reward batch_redeem_1_items 03-01 21:00:11
+ 8232 9116 非洲人 3000 redeem_reward batch_redeem_10_items 03-01 21:01:16
+ 8234 9116 非洲人 3000 redeem_reward batch_redeem_10_items 03-01 21:01:34
+ 8236 9116 非洲人 3000 redeem_reward batch_redeem_10_items 03-01 21:01:59
+ 8238 9116 非洲人 2700 redeem_reward batch_redeem_9_items 03-01 21:03:55
+ 8305 9116 非洲人 7200 redeem_reward batch_redeem_120_items 03-02 12:31:45
+ 8440 9116 非洲人 300 redeem_reward batch_redeem_1_items 03-03 02:31:13
+ 8444 9116 非洲人 300 redeem_reward batch_redeem_2_items 03-03 02:32:41
+ 8446 9116 非洲人 600 redeem_reward batch_redeem_2_items 03-03 02:34:10
+ 8448 9116 非洲人 300 redeem_reward batch_redeem_1_items 03-03 02:34:39
+ 8450 9116 非洲人 600 redeem_reward batch_redeem_2_items 03-03 02:35:39
+ 8452 9116 非洲人 500 redeem_reward batch_redeem_1_items 03-03 02:36:17
+ 8454 9116 非洲人 3200 redeem_reward batch_redeem_10_items 03-03 02:37:23
+ 8458 9116 非洲人 4450 redeem_reward batch_redeem_10_items 03-03 02:38:05
+ 8465 9116 非洲人 10250 redeem_reward batch_redeem_20_items 03-03 02:40:05
+ 8471 9116 非洲人 8750 redeem_reward batch_redeem_18_items 03-03 02:41:59
+ 8473 9116 非洲人 21000 redeem_reward batch_redeem_2_items 03-03 02:42:13
+ 8523 9116 非洲人 30000 redeem_reward batch_redeem_1_items 03-03 16:34:57
+ 8535 9116 非洲人 12050 redeem_reward batch_redeem_31_items 03-03 22:33:08
+ 8573 9116 非洲人 7000 redeem_reward batch_redeem_20_items 03-04 01:54:15
+ 8575 9116 非洲人 3600 redeem_reward batch_redeem_10_items 03-04 02:08:02
+ 8578 9116 非洲人 70000 redeem_reward batch_redeem_1_items 03-04 02:38:17
+ 8691 9116 非洲人 1250 redeem_reward batch_redeem_1_items 03-04 22:28:48
+ 8908 9116 非洲人 1800 redeem_reward batch_redeem_1_items 03-07 14:30:54
+ 用户 9116 小计: 1524320 积分 (15243.20 元)
+
+ 5620 9209 程c 500 redeem_reward batch_redeem_1_items 02-16 00:29:53
+ 5621 9209 程c 500 redeem_reward batch_redeem_1_items 02-16 00:41:42
+ 5628 9209 程c 2810 redeem_reward batch_redeem_14_items 02-16 00:51:33
+ 5641 9209 程c 500 redeem_reward batch_redeem_1_items 02-16 01:10:16
+ 5643 9209 程c 300 redeem_reward batch_redeem_1_items 02-16 01:11:03
+ 5645 9209 程c 300 redeem_reward batch_redeem_1_items 02-16 01:11:51
+ 5646 9209 程c 900 redeem_reward batch_redeem_3_items 02-16 01:14:49
+ 5647 9209 程c 300 redeem_reward batch_redeem_1_items 02-16 01:15:35
+ 5724 9209 程c 9750 redeem_reward batch_redeem_19_items 02-16 20:45:50
+ 5731 9209 程c 3000 redeem_reward batch_redeem_10_items 02-16 20:52:41
+ 5732 9209 程c 3000 redeem_reward batch_redeem_10_items 02-16 20:53:48
+ 5733 9209 程c 21500 redeem_reward batch_redeem_4_items 02-16 20:55:03
+ 5737 9209 程c 23600 redeem_reward batch_redeem_17_items 02-16 21:07:09
+ 5765 9209 程c 52700 redeem_reward batch_redeem_2_items 02-16 21:38:10
+ 5770 9209 程c 600 redeem_reward batch_redeem_2_items 02-16 21:45:42
+ 5772 9209 程c 1500 redeem_reward batch_redeem_5_items 02-16 21:46:34
+ 5796 9209 程c 1300 redeem_reward batch_redeem_7_items 02-16 22:41:06
+ 5809 9209 程c 5200 redeem_reward batch_redeem_14_items 02-16 22:48:41
+ 5922 9209 程c 600 redeem_reward batch_redeem_2_items 02-17 01:20:45
+ 5940 9209 程c 1500 redeem_reward batch_redeem_25_items 02-17 01:33:28
+ 5948 9209 程c 72110 redeem_reward batch_redeem_11_items 02-17 01:39:41
+ 6095 9209 程c 800 redeem_reward batch_redeem_2_items 02-17 02:40:19
+ 6102 9209 程c 600 redeem_reward batch_redeem_10_items 02-17 02:42:19
+ 6103 9209 程c 1200 redeem_reward batch_redeem_20_items 02-17 02:44:18
+ 6104 9209 程c 600 redeem_reward batch_redeem_10_items 02-17 02:44:43
+ 6106 9209 程c 1900 redeem_reward batch_redeem_5_items 02-17 02:57:17
+ 6176 9209 程c 300 redeem_reward batch_redeem_5_items 02-17 13:21:41
+ 6177 9209 程c 720 redeem_reward batch_redeem_4_items 02-17 13:24:00
+ 6178 9209 程c 150 redeem_reward batch_redeem_1_items 02-17 13:24:26
+ 6180 9209 程c 600 redeem_reward batch_redeem_3_items 02-17 13:25:20
+ 6190 9209 程c 1100 redeem_reward batch_redeem_2_items 02-17 14:55:18
+ 6191 9209 程c 300 redeem_reward batch_redeem_1_items 02-17 14:56:37
+ 6192 9209 程c 480 redeem_reward batch_redeem_6_items 02-17 14:57:43
+ 6193 9209 程c 1200 redeem_reward batch_redeem_4_items 02-17 14:59:28
+ 6214 9209 程c 1200 redeem_reward batch_redeem_2_items 02-17 18:02:37
+ 6241 9209 程c 34500 redeem_reward batch_redeem_3_items 02-17 18:39:47
+ 6242 9209 程c 1100 redeem_reward batch_redeem_3_items 02-17 18:40:22
+ 6243 9209 程c 600 redeem_reward batch_redeem_2_items 02-17 18:40:54
+ 6244 9209 程c 60 redeem_reward batch_redeem_1_items 02-17 18:41:15
+ 6245 9209 程c 180 redeem_reward batch_redeem_3_items 02-17 18:41:35
+ 6271 9209 程c 3300 redeem_reward batch_redeem_10_items 02-17 19:55:29
+ 6274 9209 程c 1500 redeem_reward batch_redeem_1_items 02-17 20:01:42
+ 6412 9209 程c 1200 redeem_reward batch_redeem_3_items 02-18 01:16:59
+ 6414 9209 程c 3350 redeem_reward batch_redeem_2_items 02-18 01:17:12
+ 6432 9209 程c 1700 redeem_reward batch_redeem_5_items 02-18 02:04:10
+ 6436 9209 程c 5650 redeem_reward batch_redeem_3_items 02-18 02:07:10
+ 6461 9209 程c 75000 redeem_reward batch_redeem_2_items 02-18 05:27:59
+ 6486 9209 程c 75000 redeem_reward batch_redeem_2_items 02-18 11:30:48
+ 6489 9209 程c 480 redeem_reward batch_redeem_8_items 02-18 11:58:53
+ 6490 9209 程c 1100 redeem_reward batch_redeem_3_items 02-18 11:59:57
+ 6491 9209 程c 2400 redeem_reward batch_redeem_10_items 02-18 12:01:18
+ 6492 9209 程c 360 redeem_reward batch_redeem_2_items 02-18 12:02:20
+ 6493 9209 程c 3000 redeem_reward batch_redeem_1_items 02-18 12:02:40
+ 6494 9209 程c 300 redeem_reward batch_redeem_1_items 02-18 12:03:07
+ 6495 9209 程c 150 redeem_reward batch_redeem_1_items 02-18 12:08:00
+ 6618 9209 程c 3200 redeem_reward batch_redeem_10_items 02-18 18:05:13
+ 6619 9209 程c 300 redeem_reward batch_redeem_5_items 02-18 18:06:31
+ 6621 9209 程c 720 redeem_reward batch_redeem_12_items 02-18 18:08:08
+ 6748 9209 程c 1200 redeem_reward batch_redeem_20_items 02-18 22:06:50
+ 6750 9209 程c 300 redeem_reward batch_redeem_1_items 02-18 22:08:49
+ 6753 9209 程c 540 redeem_reward batch_redeem_9_items 02-18 22:23:45
+ 6756 9209 程c 1100 redeem_reward batch_redeem_2_items 02-18 22:32:24
+ 6758 9209 程c 1100 redeem_reward batch_redeem_2_items 02-18 22:37:47
+ 6759 9209 程c 200 redeem_reward batch_redeem_2_items 02-18 22:42:22
+ 6760 9209 程c 200 redeem_reward batch_redeem_2_items 02-18 22:44:13
+ 6766 9209 程c 300 redeem_reward batch_redeem_1_items 02-18 22:57:15
+ 6769 9209 程c 4100 redeem_reward batch_redeem_2_items 02-18 23:04:26
+ 6774 9209 程c 300 redeem_reward batch_redeem_1_items 02-18 23:12:44
+ 6784 9209 程c 1700 redeem_reward batch_redeem_5_items 02-18 23:31:11
+ 6790 9209 程c 18850 redeem_reward batch_redeem_31_items 02-18 23:42:10
+ 6804 9209 程c 64500 redeem_reward batch_redeem_1_items 02-19 00:48:52
+ 6816 9209 程c 1500 redeem_reward batch_redeem_5_items 02-19 01:32:28
+ 6911 9209 程c 4200 redeem_reward batch_redeem_70_items 02-19 04:05:21
+ 6913 9209 程c 3000 redeem_reward batch_redeem_10_items 02-19 04:25:52
+ 6914 9209 程c 60 redeem_reward batch_redeem_1_items 02-19 04:27:23
+ 6916 9209 程c 1500 redeem_reward batch_redeem_5_items 02-19 04:30:24
+ 7088 9209 程c 300 redeem_reward batch_redeem_5_items 02-20 01:01:13
+ 7090 9209 程c 800 redeem_reward batch_redeem_2_items 02-20 01:01:17
+ 7140 9209 程c 1200 redeem_reward batch_redeem_2_items 02-20 20:08:35
+ 7143 9209 程c 600 redeem_reward batch_redeem_1_items 02-20 20:11:58
+ 7144 9209 程c 60 redeem_reward batch_redeem_1_items 02-20 20:12:16
+ 7340 9209 程c 22700 redeem_reward batch_redeem_13_items 02-21 01:49:19
+ 7351 9209 程c 37740 redeem_reward batch_redeem_5_items 02-21 02:02:57
+ 7352 9209 程c 37740 redeem_reward batch_redeem_5_items 02-21 02:03:03
+ 7353 9209 程c 92640 redeem_reward batch_redeem_7_items 02-21 02:03:09
+ 7358 9209 程c 480 redeem_reward batch_redeem_8_items 02-21 03:18:13
+ 7471 9209 程c 75000 redeem_reward batch_redeem_2_items 02-21 15:25:18
+ 7503 9209 程c 600 redeem_reward batch_redeem_10_items 02-21 17:21:56
+ 7642 9209 程c 1200 redeem_reward batch_redeem_2_items 02-22 21:04:59
+ 7771 9209 程c 180 redeem_reward batch_redeem_3_items 02-24 02:37:54
+ 7772 9209 程c 180 redeem_reward batch_redeem_3_items 02-24 02:39:04
+ 7773 9209 程c 4000 redeem_reward batch_redeem_1_items 02-24 02:39:22
+ 7776 9209 程c 2900 redeem_reward batch_redeem_1_items 02-24 02:44:02
+ 7779 9209 程c 4380 redeem_reward batch_redeem_2_items 02-24 02:45:10
+ 7849 9209 程c 300 redeem_reward batch_redeem_5_items 02-24 23:07:22
+ 7894 9209 程c 3000 redeem_reward batch_redeem_50_items 02-26 01:02:08
+ 7896 9209 程c 900 redeem_reward batch_redeem_3_items 02-26 01:05:24
+ 7897 9209 程c 60 redeem_reward batch_redeem_1_items 02-26 01:05:50
+ 7949 9209 程c 1400 redeem_reward batch_redeem_5_items 02-26 14:22:25
+ 8014 9209 程c 4000 redeem_reward batch_redeem_1_items 02-27 03:53:47
+ 8043 9209 程c 18000 redeem_reward batch_redeem_1_items 02-27 14:29:57
+ 8046 9209 程c 2100 redeem_reward batch_redeem_1_items 02-27 14:32:24
+ 8093 9209 程c 32400 redeem_reward batch_redeem_3_items 02-28 01:30:19
+ 8100 9209 程c 1200 redeem_reward batch_redeem_4_items 02-28 01:49:02
+ 8117 9209 程c 6300 redeem_reward batch_redeem_2_items 02-28 02:09:58
+ 8619 9209 程c 12500 redeem_reward batch_redeem_6_items 03-04 12:48:04
+ 8697 9209 程c 400 redeem_reward batch_redeem_1_items 03-04 22:41:42
+ 8701 9209 程c 500 redeem_reward batch_redeem_1_items 03-04 22:43:39
+ 8702 9209 程c 120 redeem_reward batch_redeem_2_items 03-04 22:44:26
+ 8709 9209 程c 1200 redeem_reward batch_redeem_2_items 03-04 22:45:52
+ 8711 9209 程c 8600 redeem_reward batch_redeem_10_items 03-04 22:48:01
+ 8712 9209 程c 300 redeem_reward batch_redeem_3_items 03-04 22:48:43
+ 8714 9209 程c 24250 redeem_reward batch_redeem_10_items 03-04 22:49:47
+ 8716 9209 程c 1500 redeem_reward batch_redeem_11_items 03-04 22:53:08
+ 8719 9209 程c 3100 redeem_reward batch_redeem_17_items 03-04 22:57:47
+ 8721 9209 程c 2400 redeem_reward batch_redeem_6_items 03-04 22:59:58
+ 8722 9209 程c 60 redeem_reward batch_redeem_1_items 03-04 23:00:26
+ 8723 9209 程c 15610 redeem_reward batch_redeem_11_items 03-04 23:03:06
+ 8770 9209 程c 3600 redeem_reward batch_redeem_4_items 03-05 02:18:40
+ 8772 9209 程c 1500 redeem_reward batch_redeem_4_items 03-05 02:20:49
+ 8776 9209 程c 1400 redeem_reward batch_redeem_3_items 03-05 02:22:59
+ 8778 9209 程c 4250 redeem_reward batch_redeem_8_items 03-05 02:25:15
+ 8779 9209 程c 14400 redeem_reward batch_redeem_2_items 03-05 02:26:12
+ 8782 9209 程c 6400 redeem_reward batch_redeem_20_items 03-05 02:29:24
+ 8784 9209 程c 4200 redeem_reward batch_redeem_10_items 03-05 02:30:45
+ 8786 9209 程c 3800 redeem_reward batch_redeem_20_items 03-05 02:31:47
+ 8787 9209 程c 300 redeem_reward batch_redeem_1_items 03-05 02:32:14
+ 8790 9209 程c 4450 redeem_reward batch_redeem_10_items 03-05 02:48:57
+ 8793 9209 程c 9000 redeem_reward batch_redeem_20_items 03-05 02:50:32
+ 8795 9209 程c 20300 redeem_reward batch_redeem_20_items 03-05 02:52:22
+ 8801 9209 程c 600 redeem_reward batch_redeem_2_items 03-05 10:17:07
+ 8803 9209 程c 10500 redeem_reward batch_redeem_10_items 03-05 10:19:41
+ 用户 9209 小计: 1041020 积分 (10410.20 元)
+
+ 5635 9210 非酋 2700 redeem_reward batch_redeem_3_items 02-16 00:58:32
+ 5665 9210 非酋 4700 redeem_reward batch_redeem_7_items 02-16 09:30:49
+ 5703 9210 非酋 44050 redeem_reward batch_redeem_28_items 02-16 15:07:59
+ 5718 9210 非酋 14850 redeem_reward batch_redeem_12_items 02-16 20:25:43
+ 5719 9210 非酋 44050 redeem_reward batch_redeem_8_items 02-16 20:25:57
+ 5738 9210 非酋 18500 redeem_reward batch_redeem_24_items 02-16 21:11:11
+ 5798 9210 非酋 35900 redeem_reward batch_redeem_46_items 02-16 22:43:10
+ 5818 9210 非酋 69970 redeem_reward batch_redeem_131_items 02-16 22:57:53
+ 5833 9210 非酋 41150 redeem_reward batch_redeem_30_items 02-16 22:59:30
+ 5836 9210 非酋 112500 redeem_reward batch_redeem_3_items 02-16 23:00:51
+ 5846 9210 非酋 31000 redeem_reward batch_redeem_1_items 02-16 23:43:26
+ 5856 9210 非酋 1900 redeem_reward batch_redeem_1_items 02-16 23:57:41
+ 5861 9210 非酋 47400 redeem_reward batch_redeem_11_items 02-17 00:19:21
+ 5865 9210 非酋 10650 redeem_reward batch_redeem_10_items 02-17 00:20:33
+ 5868 9210 非酋 6900 redeem_reward batch_redeem_10_items 02-17 00:21:08
+ 5870 9210 非酋 33000 redeem_reward batch_redeem_10_items 02-17 00:21:48
+ 5871 9210 非酋 18100 redeem_reward batch_redeem_3_items 02-17 00:22:53
+ 5875 9210 非酋 8000 redeem_reward batch_redeem_20_items 02-17 00:23:59
+ 5878 9210 非酋 12800 redeem_reward batch_redeem_19_items 02-17 00:24:51
+ 5927 9210 非酋 30300 redeem_reward batch_redeem_18_items 02-17 01:22:46
+ 5978 9210 非酋 6000 redeem_reward batch_redeem_100_items 02-17 01:50:12
+ 5981 9210 非酋 11500 redeem_reward batch_redeem_10_items 02-17 01:50:57
+ 5994 9210 非酋 3900 redeem_reward batch_redeem_1_items 02-17 01:55:37
+ 6005 9210 非酋 10990 redeem_reward batch_redeem_8_items 02-17 01:59:50
+ 6056 9210 非酋 3720 redeem_reward batch_redeem_13_items 02-17 02:23:08
+ 6067 9210 非酋 2000 redeem_reward batch_redeem_6_items 02-17 02:25:26
+ 6121 9210 非酋 3150 redeem_reward batch_redeem_7_items 02-17 08:58:50
+ 6123 9210 非酋 8000 redeem_reward batch_redeem_6_items 02-17 09:00:10
+ 6124 9210 非酋 6000 redeem_reward batch_redeem_100_items 02-17 09:01:55
+ 6125 9210 非酋 1400 redeem_reward batch_redeem_4_items 02-17 09:03:02
+ 6127 9210 非酋 1250 redeem_reward batch_redeem_1_items 02-17 09:04:33
+ 6128 9210 非酋 3000 redeem_reward batch_redeem_10_items 02-17 09:05:17
+ 6131 9210 非酋 38950 redeem_reward batch_redeem_39_items 02-17 09:06:52
+ 6133 9210 非酋 10100 redeem_reward batch_redeem_10_items 02-17 09:07:00
+ 6134 9210 非酋 17800 redeem_reward batch_redeem_10_items 02-17 09:12:00
+ 6140 9210 非酋 1000 redeem_reward batch_redeem_1_items 02-17 09:22:14
+ 6142 9210 非酋 53500 redeem_reward batch_redeem_19_items 02-17 09:23:49
+ 6147 9210 非酋 1250 redeem_reward batch_redeem_1_items 02-17 10:57:28
+ 6148 9210 非酋 40000 redeem_reward batch_redeem_2_items 02-17 10:58:01
+ 6149 9210 非酋 500 redeem_reward batch_redeem_1_items 02-17 11:31:56
+ 6199 9210 非酋 2320 redeem_reward batch_redeem_9_items 02-17 16:17:43
+ 6216 9210 非酋 97500 redeem_reward batch_redeem_38_items 02-17 18:07:30
+ 6259 9210 非酋 9700 redeem_reward batch_redeem_11_items 02-17 19:39:16
+ 6279 9210 非酋 75000 redeem_reward batch_redeem_2_items 02-17 20:12:33
+ 6285 9210 非酋 1650 redeem_reward batch_redeem_1_items 02-17 20:13:27
+ 6295 9210 非酋 17360 redeem_reward batch_redeem_44_items 02-17 20:26:01
+ 6297 9210 非酋 800 redeem_reward batch_redeem_1_items 02-17 20:27:12
+ 6395 9210 非酋 10500 redeem_reward batch_redeem_1_items 02-17 23:55:13
+ 6441 9210 非酋 27400 redeem_reward batch_redeem_39_items 02-18 02:30:37
+ 6442 9210 非酋 100 redeem_reward batch_redeem_1_items 02-18 02:30:48
+ 6443 9210 非酋 14500 redeem_reward batch_redeem_1_items 02-18 02:31:01
+ 6444 9210 非酋 187500 redeem_reward batch_redeem_5_items 02-18 02:42:29
+ 6448 9210 非酋 14500 redeem_reward batch_redeem_1_items 02-18 02:43:11
+ 6449 9210 非酋 129190 redeem_reward batch_redeem_5_items 02-18 02:43:17
+ 6450 9210 非酋 150000 redeem_reward batch_redeem_4_items 02-18 02:43:21
+ 6460 9210 非酋 300 redeem_reward batch_redeem_1_items 02-18 03:41:14
+ 6497 9210 非酋 145000 redeem_reward batch_redeem_1_items 02-18 14:12:05
+ 6527 9210 非酋 1300 redeem_reward batch_redeem_13_items 02-18 16:52:57
+ 6555 9210 非酋 91850 redeem_reward batch_redeem_12_items 02-18 17:07:18
+ 6561 9210 非酋 7020 redeem_reward batch_redeem_117_items 02-18 17:14:34
+ 6563 9210 非酋 1500 redeem_reward batch_redeem_1_items 02-18 17:15:55
+ 6566 9210 非酋 900 redeem_reward batch_redeem_3_items 02-18 17:19:02
+ 6589 9210 非酋 5960 redeem_reward batch_redeem_14_items 02-18 17:30:10
+ 6613 9210 非酋 3000 redeem_reward batch_redeem_10_items 02-18 17:52:36
+ 6614 9210 非酋 72700 redeem_reward batch_redeem_50_items 02-18 17:54:23
+ 6716 9210 非酋 492800 redeem_reward batch_redeem_16_items 02-18 18:40:33
+ 6813 9210 非酋 11450 redeem_reward batch_redeem_24_items 02-19 01:28:13
+ 6932 9210 非酋 106000 redeem_reward batch_redeem_2_items 02-19 08:54:52
+ 7099 9210 非酋 33900 redeem_reward batch_redeem_10_items 02-20 10:27:38
+ 7131 9210 非酋 58000 redeem_reward batch_redeem_1_items 02-20 18:43:40
+ 7146 9210 非酋 800 redeem_reward batch_redeem_2_items 02-20 20:15:09
+ 7212 9210 非酋 200 redeem_reward batch_redeem_1_items 02-20 23:52:17
+ 7432 9210 非酋 32000 redeem_reward batch_redeem_1_items 02-21 11:13:58
+ 7433 9210 非酋 300 redeem_reward batch_redeem_1_items 02-21 11:14:06
+ 7534 9210 非酋 85950 redeem_reward batch_redeem_59_items 02-21 22:43:21
+ 7540 9210 非酋 3300 redeem_reward batch_redeem_2_items 02-21 23:05:28
+ 7542 9210 非酋 843800 redeem_reward batch_redeem_18_items 02-21 23:09:43
+ 7577 9210 非酋 3900 redeem_reward batch_redeem_2_items 02-21 23:23:55
+ 7643 9210 非酋 21250 redeem_reward batch_redeem_10_items 02-22 21:22:31
+ 7715 9210 非酋 6350 redeem_reward batch_redeem_3_items 02-23 19:04:19
+ 7718 9210 非酋 91650 redeem_reward batch_redeem_122_items 02-23 19:19:41
+ 7728 9210 非酋 1250 redeem_reward batch_redeem_1_items 02-23 19:39:53
+ 7731 9210 非酋 600 redeem_reward batch_redeem_1_items 02-23 20:17:24
+ 7807 9210 非酋 1800 redeem_reward batch_redeem_1_items 02-24 14:51:36
+ 7813 9210 非酋 600 redeem_reward batch_redeem_1_items 02-24 15:45:20
+ 7827 9210 非酋 400 redeem_reward batch_redeem_1_items 02-24 21:23:01
+ 8095 9210 非酋 1220 redeem_reward batch_redeem_5_items 02-28 01:42:51
+ 8309 9210 非酋 65540 redeem_reward batch_redeem_210_items 03-02 12:48:49
+ 8374 9210 非酋 43650 redeem_reward batch_redeem_50_items 03-02 22:58:30
+ 8618 9210 非酋 3700 redeem_reward batch_redeem_9_items 03-04 12:46:16
+ 8620 9210 非酋 3400 redeem_reward batch_redeem_3_items 03-04 13:00:30
+ 8621 9210 非酋 1800 redeem_reward batch_redeem_3_items 03-04 13:01:50
+ 8622 9210 非酋 14600 redeem_reward batch_redeem_2_items 03-04 13:01:53
+ 8623 9210 非酋 480 redeem_reward batch_redeem_8_items 03-04 13:02:41
+ 用户 9210 小计: 3810670 积分 (38106.70 元)
+
+ 5672 9222 嗯?!!!! 36300 redeem_reward batch_redeem_10_items 02-16 11:35:51
+ 5673 9222 嗯?!!!! 2850 redeem_reward batch_redeem_3_items 02-16 12:02:13
+ 5674 9222 嗯?!!!! 600 redeem_reward batch_redeem_1_items 02-16 12:03:58
+ 5679 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-16 13:52:13
+ 5682 9222 嗯?!!!! 6000 redeem_reward batch_redeem_20_items 02-16 13:54:14
+ 5685 9222 嗯?!!!! 1200 redeem_reward batch_redeem_20_items 02-16 14:02:00
+ 5689 9222 嗯?!!!! 9000 redeem_reward batch_redeem_30_items 02-16 14:03:55
+ 5692 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-16 14:11:05
+ 5694 9222 嗯?!!!! 6000 redeem_reward batch_redeem_20_items 02-16 14:20:26
+ 5701 9222 嗯?!!!! 6720 redeem_reward batch_redeem_72_items 02-16 14:25:51
+ 5723 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-16 20:42:43
+ 5891 9222 嗯?!!!! 2400 redeem_reward batch_redeem_40_items 02-17 00:57:45
+ 5892 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-17 00:58:18
+ 5894 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-17 00:58:50
+ 5895 9222 嗯?!!!! 1800 redeem_reward batch_redeem_30_items 02-17 00:59:33
+ 5898 9222 嗯?!!!! 1800 redeem_reward batch_redeem_30_items 02-17 01:00:36
+ 5902 9222 嗯?!!!! 6000 redeem_reward batch_redeem_20_items 02-17 01:03:54
+ 5904 9222 嗯?!!!! 145300 redeem_reward batch_redeem_6_items 02-17 01:06:18
+ 5912 9222 嗯?!!!! 300 redeem_reward batch_redeem_5_items 02-17 01:11:20
+ 6024 9222 嗯?!!!! 11700 redeem_reward batch_redeem_39_items 02-17 02:11:02
+ 6026 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-17 02:11:52
+ 6028 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-17 02:12:24
+ 6032 9222 嗯?!!!! 3000 redeem_reward batch_redeem_50_items 02-17 02:14:16
+ 6035 9222 嗯?!!!! 1800 redeem_reward batch_redeem_30_items 02-17 02:15:01
+ 6037 9222 嗯?!!!! 1200 redeem_reward batch_redeem_20_items 02-17 02:15:44
+ 6039 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-17 02:17:04
+ 6042 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-17 02:18:05
+ 6049 9222 嗯?!!!! 180 redeem_reward batch_redeem_3_items 02-17 02:18:57
+ 6058 9222 嗯?!!!! 3000 redeem_reward batch_redeem_1_items 02-17 02:23:14
+ 6081 9222 嗯?!!!! 1800 redeem_reward batch_redeem_30_items 02-17 02:31:17
+ 6083 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-17 02:32:24
+ 6085 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-17 02:33:32
+ 6089 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-17 02:37:08
+ 6092 9222 嗯?!!!! 60 redeem_reward batch_redeem_1_items 02-17 02:39:55
+ 6097 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-17 02:40:35
+ 6100 9222 嗯?!!!! 3180 redeem_reward batch_redeem_53_items 02-17 02:42:02
+ 6120 9222 嗯?!!!! 1800 redeem_reward batch_redeem_30_items 02-17 08:05:37
+ 6151 9222 嗯?!!!! 19450 redeem_reward batch_redeem_51_items 02-17 11:42:15
+ 6197 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-17 15:36:04
+ 6260 9222 嗯?!!!! 3180 redeem_reward batch_redeem_53_items 02-17 19:40:00
+ 6261 9222 嗯?!!!! 9000 redeem_reward batch_redeem_30_items 02-17 19:40:49
+ 6264 9222 嗯?!!!! 6000 redeem_reward batch_redeem_20_items 02-17 19:41:51
+ 6266 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-17 19:42:33
+ 6377 9222 嗯?!!!! 1850 redeem_reward batch_redeem_3_items 02-17 23:39:11
+ 6383 9222 嗯?!!!! 4300 redeem_reward batch_redeem_4_items 02-17 23:41:00
+ 6385 9222 嗯?!!!! 5300 redeem_reward batch_redeem_11_items 02-17 23:44:41
+ 6387 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-17 23:45:05
+ 6393 9222 嗯?!!!! 1600 redeem_reward batch_redeem_2_items 02-17 23:53:09
+ 6397 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-18 00:11:48
+ 6400 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-18 00:18:24
+ 6405 9222 嗯?!!!! 200 redeem_reward batch_redeem_2_items 02-18 00:54:48
+ 6410 9222 嗯?!!!! 1360 redeem_reward batch_redeem_3_items 02-18 01:16:15
+ 6411 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-18 01:16:46
+ 6413 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-18 01:17:09
+ 6415 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-18 01:17:30
+ 6417 9222 嗯?!!!! 3300 redeem_reward batch_redeem_11_items 02-18 01:18:17
+ 6438 9222 嗯?!!!! 600 redeem_reward batch_redeem_2_items 02-18 02:10:23
+ 6468 9222 嗯?!!!! 1260 redeem_reward batch_redeem_21_items 02-18 08:04:30
+ 6469 9222 嗯?!!!! 1200 redeem_reward batch_redeem_20_items 02-18 08:05:09
+ 6470 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-18 08:05:28
+ 6471 9222 嗯?!!!! 180 redeem_reward batch_redeem_3_items 02-18 08:05:56
+ 6473 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-18 08:06:31
+ 6474 9222 嗯?!!!! 6000 redeem_reward batch_redeem_20_items 02-18 08:07:40
+ 6476 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-18 08:08:32
+ 6477 9222 嗯?!!!! 780 redeem_reward batch_redeem_13_items 02-18 08:13:52
+ 6478 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-18 08:14:12
+ 6480 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-18 08:14:39
+ 6509 9222 嗯?!!!! 4500 redeem_reward batch_redeem_15_items 02-18 16:37:01
+ 6534 9222 嗯?!!!! 4300 redeem_reward batch_redeem_4_items 02-18 16:55:27
+ 6539 9222 嗯?!!!! 7300 redeem_reward batch_redeem_1_items 02-18 16:58:05
+ 6543 9222 嗯?!!!! 120 redeem_reward batch_redeem_2_items 02-18 17:03:54
+ 6544 9222 嗯?!!!! 600 redeem_reward batch_redeem_10_items 02-18 17:04:44
+ 6554 9222 嗯?!!!! 9060 redeem_reward batch_redeem_31_items 02-18 17:06:57
+ 6559 9222 嗯?!!!! 5000 redeem_reward batch_redeem_1_items 02-18 17:08:19
+ 6560 9222 嗯?!!!! 800 redeem_reward batch_redeem_1_items 02-18 17:09:19
+ 6562 9222 嗯?!!!! 1800 redeem_reward batch_redeem_1_items 02-18 17:14:40
+ 6564 9222 嗯?!!!! 2500 redeem_reward batch_redeem_2_items 02-18 17:16:16
+ 6580 9222 嗯?!!!! 3000 redeem_reward batch_redeem_10_items 02-18 17:25:00
+ 6584 9222 嗯?!!!! 12000 redeem_reward batch_redeem_40_items 02-18 17:26:04
+ 6599 9222 嗯?!!!! 6120 redeem_reward batch_redeem_22_items 02-18 17:45:29
+ 6681 9222 嗯?!!!! 10200 redeem_reward batch_redeem_170_items 02-18 18:15:35
+ 6764 9222 嗯?!!!! 180 redeem_reward batch_redeem_3_items 02-18 22:56:48
+ 6783 9222 嗯?!!!! 38350 redeem_reward batch_redeem_84_items 02-18 23:30:36
+ 6788 9222 嗯?!!!! 19400 redeem_reward batch_redeem_56_items 02-18 23:37:29
+ 6793 9222 嗯?!!!! 6200 redeem_reward batch_redeem_10_items 02-18 23:47:46
+ 6796 9222 嗯?!!!! 6400 redeem_reward batch_redeem_5_items 02-18 23:55:57
+ 6824 9222 嗯?!!!! 7950 redeem_reward batch_redeem_5_items 02-19 01:44:12
+ 6881 9222 嗯?!!!! 18900 redeem_reward batch_redeem_61_items 02-19 03:15:29
+ 6883 9222 嗯?!!!! 34150 redeem_reward batch_redeem_40_items 02-19 03:17:34
+ 6888 9222 嗯?!!!! 23900 redeem_reward batch_redeem_67_items 02-19 03:23:07
+ 6893 9222 嗯?!!!! 40150 redeem_reward batch_redeem_77_items 02-19 03:25:42
+ 6902 9222 嗯?!!!! 7980 redeem_reward batch_redeem_33_items 02-19 03:33:21
+ 6978 9222 嗯?!!!! 2000 redeem_reward batch_redeem_4_items 02-19 15:24:42
+ 6984 9222 嗯?!!!! 145000 redeem_reward batch_redeem_1_items 02-19 16:10:52
+ 6993 9222 嗯?!!!! 265000 redeem_reward batch_redeem_1_items 02-19 18:23:18
+ 7292 9222 嗯?!!!! 71250 redeem_reward batch_redeem_33_items 02-21 00:28:45
+ 7313 9222 嗯?!!!! 25040 redeem_reward batch_redeem_74_items 02-21 00:57:55
+ 7640 9222 嗯?!!!! 3400 redeem_reward batch_redeem_5_items 02-22 20:53:52
+ 7723 9222 嗯?!!!! 16100 redeem_reward batch_redeem_6_items 02-23 19:29:19
+ 7726 9222 嗯?!!!! 42300 redeem_reward batch_redeem_40_items 02-23 19:31:52
+ 8302 9222 嗯?!!!! 11580 redeem_reward batch_redeem_189_items 03-02 12:24:24
+ 用户 9222 小计: 1216480 积分 (12164.80 元)
+
+ 7240 9230 巨欧小肥龙 2450 redeem_reward batch_redeem_31_items 02-21 00:05:36
+ 7247 9230 巨欧小肥龙 1200 redeem_reward batch_redeem_20_items 02-21 00:07:28
+ 7257 9230 巨欧小肥龙 4000 redeem_reward batch_redeem_1_items 02-21 00:16:04
+ 7268 9230 巨欧小肥龙 600 redeem_reward batch_redeem_1_items 02-21 00:19:54
+ 7289 9230 巨欧小肥龙 3800 redeem_reward batch_redeem_10_items 02-21 00:27:45
+ 7295 9230 巨欧小肥龙 20500 redeem_reward batch_redeem_10_items 02-21 00:31:11
+ 7304 9230 巨欧小肥龙 2700 redeem_reward batch_redeem_45_items 02-21 00:42:18
+ 7307 9230 巨欧小肥龙 1800 redeem_reward batch_redeem_12_items 02-21 00:47:09
+ 7310 9230 巨欧小肥龙 40650 redeem_reward batch_redeem_10_items 02-21 00:53:51
+ 7325 9230 巨欧小肥龙 900 redeem_reward batch_redeem_11_items 02-21 01:34:57
+ 7360 9230 巨欧小肥龙 3150 redeem_reward batch_redeem_10_items 02-21 03:41:45
+ 7362 9230 巨欧小肥龙 13600 redeem_reward batch_redeem_10_items 02-21 03:42:56
+ 7364 9230 巨欧小肥龙 3200 redeem_reward batch_redeem_10_items 02-21 03:47:07
+ 7366 9230 巨欧小肥龙 3900 redeem_reward batch_redeem_10_items 02-21 03:48:13
+ 7368 9230 巨欧小肥龙 10500 redeem_reward batch_redeem_10_items 02-21 03:49:42
+ 7370 9230 巨欧小肥龙 24300 redeem_reward batch_redeem_10_items 02-21 03:51:27
+ 7373 9230 巨欧小肥龙 3200 redeem_reward batch_redeem_10_items 02-21 04:09:14
+ 7375 9230 巨欧小肥龙 3200 redeem_reward batch_redeem_10_items 02-21 04:09:55
+ 7378 9230 巨欧小肥龙 13000 redeem_reward batch_redeem_20_items 02-21 04:10:58
+ 7381 9230 巨欧小肥龙 12300 redeem_reward batch_redeem_20_items 02-21 04:12:17
+ 7385 9230 巨欧小肥龙 8750 redeem_reward batch_redeem_30_items 02-21 04:13:25
+ 7389 9230 巨欧小肥龙 8200 redeem_reward batch_redeem_30_items 02-21 04:14:35
+ 7392 9230 巨欧小肥龙 4450 redeem_reward batch_redeem_10_items 02-21 04:15:25
+ 7393 9230 巨欧小肥龙 3100 redeem_reward batch_redeem_10_items 02-21 04:15:48
+ 7396 9230 巨欧小肥龙 7500 redeem_reward batch_redeem_20_items 02-21 04:16:32
+ 7399 9230 巨欧小肥龙 13650 redeem_reward batch_redeem_10_items 02-21 04:17:10
+ 7400 9230 巨欧小肥龙 1850 redeem_reward batch_redeem_10_items 02-21 04:17:33
+ 7402 9230 巨欧小肥龙 3400 redeem_reward batch_redeem_10_items 02-21 04:18:06
+ 7405 9230 巨欧小肥龙 24600 redeem_reward batch_redeem_10_items 02-21 04:18:58
+ 7406 9230 巨欧小肥龙 3500 redeem_reward batch_redeem_10_items 02-21 04:19:21
+ 7408 9230 巨欧小肥龙 3950 redeem_reward batch_redeem_10_items 02-21 04:19:55
+ 7410 9230 巨欧小肥龙 1650 redeem_reward batch_redeem_10_items 02-21 04:20:36
+ 7413 9230 巨欧小肥龙 3000 redeem_reward batch_redeem_10_items 02-21 04:21:34
+ 7416 9230 巨欧小肥龙 6200 redeem_reward batch_redeem_20_items 02-21 04:22:42
+ 7419 9230 巨欧小肥龙 15100 redeem_reward batch_redeem_20_items 02-21 04:23:53
+ 7420 9230 巨欧小肥龙 120 redeem_reward batch_redeem_2_items 02-21 04:32:54
+ 7421 9230 巨欧小肥龙 3000 redeem_reward batch_redeem_1_items 02-21 04:33:27
+ 7584 9230 巨欧小肥龙 2080 redeem_reward batch_redeem_13_items 02-22 00:18:55
+ 7588 9230 巨欧小肥龙 1800 redeem_reward batch_redeem_6_items 02-22 00:21:06
+ 7590 9230 巨欧小肥龙 1500 redeem_reward batch_redeem_5_items 02-22 00:21:38
+ 7638 9230 巨欧小肥龙 4300 redeem_reward batch_redeem_10_items 02-22 20:49:30
+ 7775 9230 巨欧小肥龙 4000 redeem_reward batch_redeem_1_items 02-24 02:43:38
+ 7787 9230 巨欧小肥龙 8750 redeem_reward batch_redeem_32_items 02-24 03:28:27
+ 7790 9230 巨欧小肥龙 9000 redeem_reward batch_redeem_10_items 02-24 03:29:50
+ 7791 9230 巨欧小肥龙 1700 redeem_reward batch_redeem_10_items 02-24 03:31:09
+ 7798 9230 巨欧小肥龙 9000 redeem_reward batch_redeem_30_items 02-24 03:33:59
+ 8011 9230 巨欧小肥龙 1000 redeem_reward batch_redeem_1_items 02-27 01:13:01
+ 用户 9230 小计: 324100 积分 (3241.00 元)
+
+ 5797 9248 不出last退了 500 redeem_reward batch_redeem_1_items 02-16 22:41:35
+ 5806 9248 不出last退了 6500 redeem_reward batch_redeem_2_items 02-16 22:47:56
+ 5817 9248 不出last退了 3800 redeem_reward batch_redeem_51_items 02-16 22:56:59
+ 5832 9248 不出last退了 300 redeem_reward batch_redeem_1_items 02-16 22:58:47
+ 5838 9248 不出last退了 1000 redeem_reward batch_redeem_1_items 02-16 23:04:20
+ 5839 9248 不出last退了 300 redeem_reward batch_redeem_1_items 02-16 23:04:55
+ 6200 9248 不出last退了 360 redeem_reward batch_redeem_2_items 02-17 16:29:41
+ 6201 9248 不出last退了 1140 redeem_reward batch_redeem_19_items 02-17 16:33:45
+ 6202 9248 不出last退了 3000 redeem_reward batch_redeem_50_items 02-17 16:41:26
+ 6203 9248 不出last退了 3000 redeem_reward batch_redeem_1_items 02-17 16:42:47
+ 6212 9248 不出last退了 400 redeem_reward batch_redeem_1_items 02-17 17:36:10
+ 6255 9248 不出last退了 5520 redeem_reward batch_redeem_92_items 02-17 19:19:30
+ 6464 9248 不出last退了 7300 redeem_reward batch_redeem_1_items 02-18 06:23:12
+ 6465 9248 不出last退了 7700 redeem_reward batch_redeem_19_items 02-18 06:29:14
+ 6466 9248 不出last退了 2500 redeem_reward batch_redeem_3_items 02-18 06:29:19
+ 6467 9248 不出last退了 2450 redeem_reward batch_redeem_5_items 02-18 06:31:24
+ 6744 9248 不出last退了 600 redeem_reward batch_redeem_10_items 02-18 21:20:15
+ 6765 9248 不出last退了 6300 redeem_reward batch_redeem_5_items 02-18 22:57:09
+ 6770 9248 不出last退了 53600 redeem_reward batch_redeem_4_items 02-18 23:08:27
+ 6921 9248 不出last退了 6360 redeem_reward batch_redeem_106_items 02-19 07:09:04
+ 6923 9248 不出last退了 4600 redeem_reward batch_redeem_10_items 02-19 07:11:39
+ 6925 9248 不出last退了 4400 redeem_reward batch_redeem_10_items 02-19 07:13:24
+ 6927 9248 不出last退了 8400 redeem_reward batch_redeem_12_items 02-19 07:23:38
+ 6929 9248 不出last退了 10700 redeem_reward batch_redeem_5_items 02-19 07:24:19
+ 6930 9248 不出last退了 2200 redeem_reward batch_redeem_5_items 02-19 07:25:13
+ 6931 9248 不出last退了 3600 redeem_reward batch_redeem_14_items 02-19 07:42:01
+ 6950 9248 不出last退了 17540 redeem_reward batch_redeem_5_items 02-19 13:06:35
+ 6951 9248 不出last退了 83500 redeem_reward batch_redeem_2_items 02-19 13:20:15
+ 6956 9248 不出last退了 150000 redeem_reward batch_redeem_4_items 02-19 13:22:13
+ 6963 9248 不出last退了 800 redeem_reward batch_redeem_2_items 02-19 13:27:30
+ 7018 9248 不出last退了 1800 redeem_reward batch_redeem_30_items 02-19 18:37:38
+ 7019 9248 不出last退了 600 redeem_reward batch_redeem_10_items 02-19 18:38:10
+ 7022 9248 不出last退了 17000 redeem_reward batch_redeem_1_items 02-19 18:45:28
+ 7028 9248 不出last退了 4000 redeem_reward batch_redeem_10_items 02-19 18:48:28
+ 7030 9248 不出last退了 5000 redeem_reward batch_redeem_4_items 02-19 18:55:54
+ 7031 9248 不出last退了 37400 redeem_reward batch_redeem_3_items 02-19 18:55:58
+ 7233 9248 不出last退了 21160 redeem_reward batch_redeem_21_items 02-21 00:02:47
+ 7235 9248 不出last退了 3050 redeem_reward batch_redeem_2_items 02-21 00:04:13
+ 7239 9248 不出last退了 1400 redeem_reward batch_redeem_2_items 02-21 00:05:20
+ 7241 9248 不出last退了 180 redeem_reward batch_redeem_3_items 02-21 00:05:49
+ 7543 9248 不出last退了 2100 redeem_reward batch_redeem_5_items 02-21 23:10:03
+ 7563 9248 不出last退了 800 redeem_reward batch_redeem_1_items 02-21 23:10:41
+ 7591 9248 不出last退了 740 redeem_reward batch_redeem_5_items 02-22 00:47:01
+ 7594 9248 不出last退了 22400 redeem_reward batch_redeem_20_items 02-22 00:48:51
+ 7595 9248 不出last退了 2400 redeem_reward batch_redeem_3_items 02-22 00:49:30
+ 7596 9248 不出last退了 500 redeem_reward batch_redeem_1_items 02-22 00:49:59
+ 7606 9248 不出last退了 7900 redeem_reward batch_redeem_5_items 02-22 07:57:02
+ 7633 9248 不出last退了 3600 redeem_reward batch_redeem_2_items 02-22 20:30:53
+ 7652 9248 不出last退了 32240 redeem_reward batch_redeem_5_items 02-22 23:46:16
+ 7806 9248 不出last退了 4000 redeem_reward batch_redeem_1_items 02-24 14:34:33
+ 7808 9248 不出last退了 4000 redeem_reward batch_redeem_1_items 02-24 14:51:39
+ 7810 9248 不出last退了 7500 redeem_reward batch_redeem_1_items 02-24 15:00:51
+ 7811 9248 不出last退了 3060 redeem_reward batch_redeem_51_items 02-24 15:01:59
+ 7812 9248 不出last退了 9200 redeem_reward batch_redeem_5_items 02-24 15:08:57
+ 8177 9248 不出last退了 2190 redeem_reward batch_redeem_1_items 02-28 21:59:42
+ 8179 9248 不出last退了 1200 redeem_reward batch_redeem_2_items 02-28 22:02:28
+ 8616 9248 不出last退了 10410 redeem_reward batch_redeem_11_items 03-04 12:13:49
+ 8617 9248 不出last退了 9300 redeem_reward batch_redeem_2_items 03-04 12:15:51
+ 8625 9248 不出last退了 1800 redeem_reward batch_redeem_2_items 03-04 14:13:47
+ 8628 9248 不出last退了 3440 redeem_reward batch_redeem_2_items 03-04 17:10:16
+ 8629 9248 不出last退了 25300 redeem_reward batch_redeem_35_items 03-04 17:14:38
+ 8630 9248 不出last退了 600 redeem_reward batch_redeem_1_items 03-04 17:19:26
+ 8631 9248 不出last退了 150 redeem_reward batch_redeem_1_items 03-04 17:24:25
+ 用户 9248 小计: 644790 积分 (6447.90 元)
+
+ 6616 9305 新人 500 redeem_reward batch_redeem_1_items 02-18 18:00:55
+ 6620 9305 新人 500 redeem_reward batch_redeem_1_items 02-18 18:06:37
+ 6622 9305 新人 1250 redeem_reward batch_redeem_1_items 02-18 18:10:02
+ 6703 9305 新人 300 redeem_reward batch_redeem_2_items 02-18 18:17:16
+ 6706 9305 新人 300 redeem_reward batch_redeem_3_items 02-18 18:19:46
+ 6708 9305 新人 4240 redeem_reward batch_redeem_5_items 02-18 18:24:08
+ 6709 9305 新人 7000 redeem_reward batch_redeem_1_items 02-18 18:35:08
+ 6712 9305 新人 300 redeem_reward batch_redeem_5_items 02-18 18:38:05
+ 6714 9305 新人 2300 redeem_reward batch_redeem_6_items 02-18 18:39:44
+ 6717 9305 新人 1800 redeem_reward batch_redeem_6_items 02-18 18:41:19
+ 6719 9305 新人 300 redeem_reward batch_redeem_1_items 02-18 18:42:06
+ 6721 9305 新人 1500 redeem_reward batch_redeem_5_items 02-18 18:43:27
+ 6723 9305 新人 700 redeem_reward batch_redeem_2_items 02-18 18:44:20
+ 6725 9305 新人 600 redeem_reward batch_redeem_2_items 02-18 18:45:21
+ 6728 9305 新人 600 redeem_reward batch_redeem_10_items 02-18 18:50:18
+ 6809 9305 新人 7200 redeem_reward batch_redeem_1_items 02-19 01:13:39
+ 6811 9305 新人 1500 redeem_reward batch_redeem_3_items 02-19 01:20:17
+ 6812 9305 新人 300 redeem_reward batch_redeem_2_items 02-19 01:21:32
+ 6818 9305 新人 7100 redeem_reward batch_redeem_1_items 02-19 01:37:28
+ 6822 9305 新人 300 redeem_reward batch_redeem_2_items 02-19 01:39:27
+ 6826 9305 新人 16000 redeem_reward batch_redeem_1_items 02-19 01:52:47
+ 6827 9305 新人 16000 redeem_reward batch_redeem_1_items 02-19 01:54:21
+ 6831 9305 新人 39700 redeem_reward batch_redeem_2_items 02-19 02:11:23
+ 6836 9305 新人 900 redeem_reward batch_redeem_3_items 02-19 02:25:38
+ 6838 9305 新人 1800 redeem_reward batch_redeem_10_items 02-19 02:26:29
+ 6840 9305 新人 2450 redeem_reward batch_redeem_4_items 02-19 02:27:25
+ 6842 9305 新人 500 redeem_reward batch_redeem_2_items 02-19 02:28:23
+ 6843 9305 新人 990 redeem_reward batch_redeem_9_items 02-19 02:41:48
+ 6846 9305 新人 1750 redeem_reward batch_redeem_10_items 02-19 02:43:07
+ 6848 9305 新人 550 redeem_reward batch_redeem_3_items 02-19 02:43:46
+ 6850 9305 新人 500 redeem_reward batch_redeem_3_items 02-19 02:44:22
+ 6851 9305 新人 600 redeem_reward batch_redeem_1_items 02-19 02:45:39
+ 6852 9305 新人 600 redeem_reward batch_redeem_1_items 02-19 02:46:31
+ 6854 9305 新人 1800 redeem_reward batch_redeem_11_items 02-19 02:47:37
+ 6856 9305 新人 1300 redeem_reward batch_redeem_2_items 02-19 02:51:28
+ 6857 9305 新人 300 redeem_reward batch_redeem_1_items 02-19 02:52:22
+ 6859 9305 新人 700 redeem_reward batch_redeem_2_items 02-19 02:53:51
+ 6862 9305 新人 500 redeem_reward batch_redeem_1_items 02-19 02:59:24
+ 6864 9305 新人 650 redeem_reward batch_redeem_1_items 02-19 03:00:15
+ 6868 9305 新人 2500 redeem_reward batch_redeem_1_items 02-19 03:01:17
+ 6870 9305 新人 1350 redeem_reward batch_redeem_7_items 02-19 03:03:07
+ 6872 9305 新人 1650 redeem_reward batch_redeem_8_items 02-19 03:04:25
+ 6874 9305 新人 3450 redeem_reward batch_redeem_4_items 02-19 03:05:20
+ 6876 9305 新人 1650 redeem_reward batch_redeem_10_items 02-19 03:05:46
+ 6878 9305 新人 450 redeem_reward batch_redeem_3_items 02-19 03:06:15
+ 6991 9305 新人 500 redeem_reward batch_redeem_3_items 02-19 17:57:17
+ 7061 9305 新人 550 redeem_reward batch_redeem_3_items 02-19 23:33:40
+ 7062 9305 新人 300 redeem_reward batch_redeem_1_items 02-19 23:34:39
+ 7174 9305 新人 600 redeem_reward batch_redeem_4_items 02-20 23:31:20
+ 7176 9305 新人 1250 redeem_reward batch_redeem_4_items 02-20 23:32:33
+ 7177 9305 新人 4000 redeem_reward batch_redeem_1_items 02-20 23:32:40
+ 7178 9305 新人 300 redeem_reward batch_redeem_1_items 02-20 23:35:08
+ 7180 9305 新人 8230 redeem_reward batch_redeem_5_items 02-20 23:35:17
+ 7183 9305 新人 1500 redeem_reward batch_redeem_1_items 02-20 23:36:20
+ 7185 9305 新人 1600 redeem_reward batch_redeem_3_items 02-20 23:36:52
+ 7188 9305 新人 550 redeem_reward batch_redeem_2_items 02-20 23:37:53
+ 7189 9305 新人 150 redeem_reward batch_redeem_1_items 02-20 23:37:56
+ 7191 9305 新人 500 redeem_reward batch_redeem_3_items 02-20 23:38:56
+ 7193 9305 新人 600 redeem_reward batch_redeem_4_items 02-20 23:39:32
+ 7194 9305 新人 300 redeem_reward batch_redeem_1_items 02-20 23:45:44
+ 7196 9305 新人 600 redeem_reward batch_redeem_1_items 02-20 23:46:32
+ 7198 9305 新人 600 redeem_reward batch_redeem_1_items 02-20 23:46:58
+ 7200 9305 新人 500 redeem_reward batch_redeem_1_items 02-20 23:47:21
+ 7202 9305 新人 3600 redeem_reward batch_redeem_10_items 02-20 23:47:50
+ 7205 9305 新人 300 redeem_reward batch_redeem_1_items 02-20 23:49:08
+ 7208 9305 新人 600 redeem_reward batch_redeem_2_items 02-20 23:50:07
+ 7213 9305 新人 900 redeem_reward batch_redeem_2_items 02-20 23:52:38
+ 7215 9305 新人 500 redeem_reward batch_redeem_1_items 02-20 23:53:13
+ 7218 9305 新人 1500 redeem_reward batch_redeem_5_items 02-20 23:54:27
+ 7219 9305 新人 2000 redeem_reward batch_redeem_1_items 02-20 23:54:34
+ 7222 9305 新人 1200 redeem_reward batch_redeem_4_items 02-20 23:55:16
+ 7224 9305 新人 900 redeem_reward batch_redeem_3_items 02-20 23:56:04
+ 7225 9305 新人 300 redeem_reward batch_redeem_1_items 02-20 23:56:28
+ 7226 9305 新人 7500 redeem_reward batch_redeem_1_items 02-20 23:56:34
+ 7228 9305 新人 400 redeem_reward batch_redeem_1_items 02-20 23:57:40
+ 7242 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 00:06:26
+ 7244 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 00:07:06
+ 7248 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 00:07:58
+ 7250 9305 新人 900 redeem_reward batch_redeem_2_items 02-21 00:09:18
+ 7252 9305 新人 650 redeem_reward batch_redeem_2_items 02-21 00:10:06
+ 7254 9305 新人 1200 redeem_reward batch_redeem_3_items 02-21 00:10:46
+ 7258 9305 新人 500 redeem_reward batch_redeem_1_items 02-21 00:16:12
+ 7260 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 00:17:17
+ 7262 9305 新人 1200 redeem_reward batch_redeem_4_items 02-21 00:17:53
+ 7266 9305 新人 1000 redeem_reward batch_redeem_1_items 02-21 00:19:07
+ 7269 9305 新人 600 redeem_reward batch_redeem_1_items 02-21 00:20:19
+ 7273 9305 新人 4000 redeem_reward batch_redeem_1_items 02-21 00:21:18
+ 7275 9305 新人 600 redeem_reward batch_redeem_2_items 02-21 00:22:14
+ 7279 9305 新人 700 redeem_reward batch_redeem_2_items 02-21 00:23:56
+ 7283 9305 新人 1200 redeem_reward batch_redeem_2_items 02-21 00:25:29
+ 7287 9305 新人 2200 redeem_reward batch_redeem_3_items 02-21 00:27:29
+ 7290 9305 新人 1200 redeem_reward batch_redeem_2_items 02-21 00:28:37
+ 7293 9305 新人 9400 redeem_reward batch_redeem_3_items 02-21 00:29:35
+ 7296 9305 新人 2200 redeem_reward batch_redeem_2_items 02-21 00:31:46
+ 7297 9305 新人 1000 redeem_reward batch_redeem_2_items 02-21 00:34:02
+ 7298 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 00:34:38
+ 7299 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 00:35:04
+ 7314 9305 新人 4000 redeem_reward batch_redeem_1_items 02-21 01:01:10
+ 7319 9305 新人 37500 redeem_reward batch_redeem_1_items 02-21 01:17:13
+ 7326 9305 新人 1500 redeem_reward batch_redeem_1_items 02-21 01:34:59
+ 7329 9305 新人 450 redeem_reward batch_redeem_2_items 02-21 01:39:24
+ 7349 9305 新人 60 redeem_reward batch_redeem_1_items 02-21 01:57:32
+ 7427 9305 新人 9500 redeem_reward batch_redeem_1_items 02-21 04:51:41
+ 7499 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 17:10:25
+ 7500 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 17:11:18
+ 7501 9305 新人 16000 redeem_reward batch_redeem_1_items 02-21 17:12:32
+ 7510 9305 新人 600 redeem_reward batch_redeem_1_items 02-21 19:33:02
+ 7512 9305 新人 300 redeem_reward batch_redeem_1_items 02-21 19:34:40
+ 7587 9305 新人 600 redeem_reward batch_redeem_1_items 02-22 00:20:30
+ 7622 9305 新人 250 redeem_reward batch_redeem_1_items 02-22 15:28:51
+ 7661 9305 新人 450 redeem_reward batch_redeem_3_items 02-23 05:16:03
+ 7662 9305 新人 300 redeem_reward batch_redeem_1_items 02-23 05:16:53
+ 7663 9305 新人 150 redeem_reward batch_redeem_1_items 02-23 05:17:45
+ 7664 9305 新人 1200 redeem_reward batch_redeem_2_items 02-23 05:19:32
+ 7665 9305 新人 600 redeem_reward batch_redeem_3_items 02-23 05:20:45
+ 7666 9305 新人 500 redeem_reward batch_redeem_3_items 02-23 08:13:57
+ 7667 9305 新人 1100 redeem_reward batch_redeem_6_items 02-23 08:15:52
+ 7668 9305 新人 750 redeem_reward batch_redeem_5_items 02-23 08:16:59
+ 7669 9305 新人 150 redeem_reward batch_redeem_1_items 02-23 08:17:44
+ 7670 9305 新人 1500 redeem_reward batch_redeem_1_items 02-23 08:19:21
+ 7694 9305 新人 150 redeem_reward batch_redeem_1_items 02-23 17:22:54
+ 7695 9305 新人 73100 redeem_reward batch_redeem_5_items 02-23 17:23:01
+ 7696 9305 新人 4100 redeem_reward batch_redeem_3_items 02-23 17:27:01
+ 7697 9305 新人 1500 redeem_reward batch_redeem_1_items 02-23 17:27:44
+ 7698 9305 新人 450 redeem_reward batch_redeem_3_items 02-23 17:28:31
+ 7699 9305 新人 300 redeem_reward batch_redeem_1_items 02-23 17:29:13
+ 7700 9305 新人 200 redeem_reward batch_redeem_1_items 02-23 17:29:39
+ 7701 9305 新人 150 redeem_reward batch_redeem_1_items 02-23 17:30:19
+ 7702 9305 新人 300 redeem_reward batch_redeem_1_items 02-23 17:30:55
+ 7706 9305 新人 150 redeem_reward batch_redeem_1_items 02-23 17:32:05
+ 用户 9305 小计: 368370 积分 (3683.70 元)
+
+ 6752 9336 有冰的帝君 128200 redeem_reward batch_redeem_370_items 02-18 22:22:59
+ 6768 9336 有冰的帝君 400 redeem_reward batch_redeem_4_items 02-18 23:04:11
+ 6782 9336 有冰的帝君 12400 redeem_reward batch_redeem_36_items 02-18 23:24:51
+ 6785 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-18 23:31:18
+ 6834 9336 有冰的帝君 3900 redeem_reward batch_redeem_53_items 02-19 02:15:50
+ 6971 9336 有冰的帝君 3000 redeem_reward batch_redeem_10_items 02-19 15:11:08
+ 6972 9336 有冰的帝君 3000 redeem_reward batch_redeem_10_items 02-19 15:15:26
+ 6979 9336 有冰的帝君 6000 redeem_reward batch_redeem_20_items 02-19 15:24:46
+ 6983 9336 有冰的帝君 7800 redeem_reward batch_redeem_26_items 02-19 15:32:13
+ 7102 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 02-20 12:32:28
+ 7103 9336 有冰的帝君 400 redeem_reward batch_redeem_1_items 02-20 12:33:17
+ 7104 9336 有冰的帝君 2900 redeem_reward batch_redeem_5_items 02-20 12:36:42
+ 7105 9336 有冰的帝君 1700 redeem_reward batch_redeem_5_items 02-20 12:42:30
+ 7106 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-20 12:43:46
+ 7107 9336 有冰的帝君 500 redeem_reward batch_redeem_1_items 02-20 12:44:22
+ 7139 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 02-20 20:08:35
+ 7151 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-20 20:29:30
+ 7153 9336 有冰的帝君 66750 redeem_reward batch_redeem_69_items 02-20 21:00:50
+ 7155 9336 有冰的帝君 1200 redeem_reward batch_redeem_20_items 02-20 21:03:30
+ 7230 9336 有冰的帝君 1600 redeem_reward batch_redeem_5_items 02-21 00:00:56
+ 7231 9336 有冰的帝君 2000 redeem_reward batch_redeem_1_items 02-21 00:01:45
+ 7232 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-21 00:02:36
+ 7234 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 02-21 00:03:23
+ 7236 9336 有冰的帝君 500 redeem_reward batch_redeem_1_items 02-21 00:04:31
+ 7238 9336 有冰的帝君 6000 redeem_reward batch_redeem_1_items 02-21 00:05:11
+ 7246 9336 有冰的帝君 2300 redeem_reward batch_redeem_4_items 02-21 00:07:26
+ 7251 9336 有冰的帝君 1300 redeem_reward batch_redeem_2_items 02-21 00:09:27
+ 7255 9336 有冰的帝君 1000 redeem_reward batch_redeem_2_items 02-21 00:12:36
+ 7265 9336 有冰的帝君 12200 redeem_reward batch_redeem_20_items 02-21 00:18:52
+ 7277 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-21 00:22:47
+ 7278 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-21 00:22:56
+ 7281 9336 有冰的帝君 100 redeem_reward batch_redeem_1_items 02-21 00:24:44
+ 7285 9336 有冰的帝君 650 redeem_reward batch_redeem_1_items 02-21 00:26:40
+ 7311 9336 有冰的帝君 180 redeem_reward batch_redeem_3_items 02-21 00:55:14
+ 7315 9336 有冰的帝君 5500 redeem_reward batch_redeem_3_items 02-21 01:04:22
+ 7316 9336 有冰的帝君 1200 redeem_reward batch_redeem_3_items 02-21 01:13:51
+ 7318 9336 有冰的帝君 32000 redeem_reward batch_redeem_1_items 02-21 01:16:27
+ 7320 9336 有冰的帝君 360 redeem_reward batch_redeem_6_items 02-21 01:21:08
+ 7603 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-22 01:44:31
+ 7691 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-23 15:48:11
+ 7692 9336 有冰的帝君 400 redeem_reward batch_redeem_1_items 02-23 15:51:52
+ 7693 9336 有冰的帝君 400 redeem_reward batch_redeem_1_items 02-23 15:52:32
+ 7757 9336 有冰的帝君 9800 redeem_reward batch_redeem_10_items 02-24 00:37:05
+ 7759 9336 有冰的帝君 18000 redeem_reward batch_redeem_300_items 02-24 01:07:27
+ 7766 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 02-24 01:46:21
+ 7774 9336 有冰的帝君 4000 redeem_reward batch_redeem_1_items 02-24 02:42:09
+ 7778 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 02-24 02:44:36
+ 7817 9336 有冰的帝君 1300 redeem_reward batch_redeem_2_items 02-24 18:26:58
+ 7843 9336 有冰的帝君 38200 redeem_reward batch_redeem_38_items 02-24 22:44:33
+ 7859 9336 有冰的帝君 31200 redeem_reward batch_redeem_38_items 02-25 02:50:57
+ 7861 9336 有冰的帝君 2700 redeem_reward batch_redeem_7_items 02-25 02:57:48
+ 7863 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-25 03:25:08
+ 7899 9336 有冰的帝君 2190 redeem_reward batch_redeem_1_items 02-26 02:09:28
+ 7901 9336 有冰的帝君 7300 redeem_reward batch_redeem_1_items 02-26 02:11:31
+ 7906 9336 有冰的帝君 4500 redeem_reward batch_redeem_15_items 02-26 02:20:43
+ 7909 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 02-26 02:22:07
+ 7910 9336 有冰的帝君 1850 redeem_reward batch_redeem_2_items 02-26 02:23:31
+ 7912 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-26 02:24:06
+ 7914 9336 有冰的帝君 1800 redeem_reward batch_redeem_1_items 02-26 02:25:05
+ 7916 9336 有冰的帝君 2190 redeem_reward batch_redeem_1_items 02-26 02:25:54
+ 7918 9336 有冰的帝君 2190 redeem_reward batch_redeem_1_items 02-26 02:26:38
+ 7920 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-26 02:27:27
+ 7927 9336 有冰的帝君 4900 redeem_reward batch_redeem_10_items 02-26 02:30:42
+ 7928 9336 有冰的帝君 250 redeem_reward batch_redeem_1_items 02-26 02:32:19
+ 7929 9336 有冰的帝君 600 redeem_reward batch_redeem_3_items 02-26 02:33:20
+ 7932 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-26 03:04:11
+ 7933 9336 有冰的帝君 4000 redeem_reward batch_redeem_1_items 02-26 03:23:39
+ 7956 9336 有冰的帝君 7300 redeem_reward batch_redeem_1_items 02-26 17:40:17
+ 7958 9336 有冰的帝君 5000 redeem_reward batch_redeem_1_items 02-26 17:41:14
+ 7960 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-26 17:43:08
+ 7962 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-26 17:43:40
+ 7964 9336 有冰的帝君 1800 redeem_reward batch_redeem_1_items 02-26 17:44:17
+ 7966 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-26 17:44:54
+ 7968 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-26 17:45:31
+ 7970 9336 有冰的帝君 5000 redeem_reward batch_redeem_1_items 02-26 17:47:37
+ 7971 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-26 17:48:49
+ 7973 9336 有冰的帝君 1800 redeem_reward batch_redeem_1_items 02-26 17:49:52
+ 7974 9336 有冰的帝君 650 redeem_reward batch_redeem_1_items 02-26 17:50:44
+ 7975 9336 有冰的帝君 17000 redeem_reward batch_redeem_1_items 02-26 17:52:35
+ 7976 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 02-26 17:53:25
+ 7977 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 02-26 17:53:55
+ 7978 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 02-26 17:54:48
+ 7979 9336 有冰的帝君 1500 redeem_reward batch_redeem_1_items 02-26 17:55:36
+ 7980 9336 有冰的帝君 1000 redeem_reward batch_redeem_1_items 02-26 17:56:08
+ 7981 9336 有冰的帝君 400 redeem_reward batch_redeem_1_items 02-26 17:56:40
+ 7982 9336 有冰的帝君 1000 redeem_reward batch_redeem_1_items 02-26 17:57:14
+ 7983 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-26 17:57:47
+ 7984 9336 有冰的帝君 1500 redeem_reward batch_redeem_3_items 02-26 17:58:45
+ 7985 9336 有冰的帝君 700 redeem_reward batch_redeem_2_items 02-26 17:59:34
+ 7986 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-26 18:00:02
+ 7987 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 02-26 18:00:46
+ 8001 9336 有冰的帝君 233700 redeem_reward batch_redeem_426_items 02-26 22:17:58
+ 8010 9336 有冰的帝君 48000 redeem_reward batch_redeem_3_items 02-26 23:53:16
+ 8012 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-27 01:18:21
+ 8013 9336 有冰的帝君 1600 redeem_reward batch_redeem_4_items 02-27 03:16:44
+ 8067 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-27 20:39:27
+ 8068 9336 有冰的帝君 500 redeem_reward batch_redeem_1_items 02-27 20:44:54
+ 8077 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 02-27 22:40:17
+ 8089 9336 有冰的帝君 500 redeem_reward batch_redeem_1_items 02-28 01:00:59
+ 8103 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 02-28 01:55:41
+ 8104 9336 有冰的帝君 4000 redeem_reward batch_redeem_1_items 02-28 01:56:19
+ 8106 9336 有冰的帝君 2000 redeem_reward batch_redeem_1_items 02-28 01:57:39
+ 8108 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 02-28 01:58:22
+ 8110 9336 有冰的帝君 1800 redeem_reward batch_redeem_1_items 02-28 01:59:07
+ 8112 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 02-28 02:00:17
+ 8114 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 02-28 02:00:47
+ 8128 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-28 12:21:55
+ 8130 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 02-28 12:22:31
+ 8131 9336 有冰的帝君 147100 redeem_reward batch_redeem_8_items 02-28 12:51:51
+ 8132 9336 有冰的帝君 247600 redeem_reward batch_redeem_38_items 02-28 12:54:46
+ 8137 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 02-28 16:54:42
+ 8141 9336 有冰的帝君 1200 redeem_reward batch_redeem_4_items 02-28 19:57:16
+ 8195 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-01 05:35:16
+ 8196 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-01 05:35:59
+ 8197 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 03-01 05:36:38
+ 8200 9336 有冰的帝君 2400 redeem_reward batch_redeem_8_items 03-01 10:03:51
+ 8202 9336 有冰的帝君 20800 redeem_reward batch_redeem_1_items 03-01 10:04:50
+ 8203 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 03-01 10:08:35
+ 8204 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 03-01 10:14:01
+ 8205 9336 有冰的帝君 4000 redeem_reward batch_redeem_1_items 03-01 10:15:11
+ 8206 9336 有冰的帝君 1500 redeem_reward batch_redeem_1_items 03-01 10:16:19
+ 8207 9336 有冰的帝君 4000 redeem_reward batch_redeem_1_items 03-01 10:17:22
+ 8208 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-01 10:26:09
+ 8209 9336 有冰的帝君 100 redeem_reward batch_redeem_1_items 03-01 10:29:24
+ 8210 9336 有冰的帝君 6200 redeem_reward batch_redeem_10_items 03-01 10:30:15
+ 8211 9336 有冰的帝君 1000 redeem_reward batch_redeem_10_items 03-01 10:31:39
+ 8213 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 03-01 10:34:17
+ 8214 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-01 10:44:11
+ 8215 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 03-01 10:44:42
+ 8217 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-01 16:07:28
+ 8218 9336 有冰的帝君 400 redeem_reward batch_redeem_1_items 03-01 16:08:53
+ 8219 9336 有冰的帝君 1000 redeem_reward batch_redeem_1_items 03-01 16:10:13
+ 8220 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-01 16:10:46
+ 8221 9336 有冰的帝君 1000 redeem_reward batch_redeem_1_items 03-01 16:11:37
+ 8223 9336 有冰的帝君 5300 redeem_reward batch_redeem_6_items 03-01 16:15:41
+ 8230 9336 有冰的帝君 42000 redeem_reward batch_redeem_1_items 03-01 20:25:47
+ 8243 9336 有冰的帝君 4600 redeem_reward batch_redeem_10_items 03-01 22:23:30
+ 8246 9336 有冰的帝君 6200 redeem_reward batch_redeem_5_items 03-01 22:25:56
+ 8249 9336 有冰的帝君 1500 redeem_reward batch_redeem_1_items 03-01 22:32:51
+ 8252 9336 有冰的帝君 600 redeem_reward batch_redeem_10_items 03-01 22:38:48
+ 8256 9336 有冰的帝君 5200 redeem_reward batch_redeem_3_items 03-01 23:56:51
+ 8258 9336 有冰的帝君 3600 redeem_reward batch_redeem_10_items 03-01 23:58:17
+ 8260 9336 有冰的帝君 2200 redeem_reward batch_redeem_5_items 03-02 00:00:14
+ 8262 9336 有冰的帝君 2400 redeem_reward batch_redeem_6_items 03-02 00:03:27
+ 8264 9336 有冰的帝君 2100 redeem_reward batch_redeem_6_items 03-02 00:04:08
+ 8266 9336 有冰的帝君 900 redeem_reward batch_redeem_3_items 03-02 00:05:01
+ 8270 9336 有冰的帝君 1200 redeem_reward batch_redeem_12_items 03-02 00:54:57
+ 8272 9336 有冰的帝君 600 redeem_reward batch_redeem_10_items 03-02 00:55:39
+ 8273 9336 有冰的帝君 900 redeem_reward batch_redeem_5_items 03-02 00:58:18
+ 8275 9336 有冰的帝君 700 redeem_reward batch_redeem_2_items 03-02 00:59:31
+ 8277 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 03-02 01:00:14
+ 8279 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-02 01:00:59
+ 8280 9336 有冰的帝君 2100 redeem_reward batch_redeem_5_items 03-02 01:15:20
+ 8282 9336 有冰的帝君 1900 redeem_reward batch_redeem_5_items 03-02 01:21:49
+ 8285 9336 有冰的帝君 4800 redeem_reward batch_redeem_14_items 03-02 01:25:22
+ 8287 9336 有冰的帝君 3200 redeem_reward batch_redeem_5_items 03-02 01:27:54
+ 8289 9336 有冰的帝君 5400 redeem_reward batch_redeem_3_items 03-02 01:29:19
+ 8292 9336 有冰的帝君 48350 redeem_reward batch_redeem_100_items 03-02 02:02:30
+ 8293 9336 有冰的帝君 4490 redeem_reward batch_redeem_2_items 03-02 02:02:56
+ 8294 9336 有冰的帝君 360 redeem_reward batch_redeem_6_items 03-02 02:25:26
+ 8295 9336 有冰的帝君 120 redeem_reward batch_redeem_2_items 03-02 02:26:08
+ 8313 9336 有冰的帝君 150 redeem_reward batch_redeem_1_items 03-02 14:22:48
+ 8314 9336 有冰的帝君 2300 redeem_reward batch_redeem_2_items 03-02 14:25:36
+ 8316 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 03-02 14:26:32
+ 8318 9336 有冰的帝君 900 redeem_reward batch_redeem_3_items 03-02 14:27:23
+ 8320 9336 有冰的帝君 600 redeem_reward batch_redeem_10_items 03-02 14:28:00
+ 8322 9336 有冰的帝君 600 redeem_reward batch_redeem_10_items 03-02 14:28:25
+ 8323 9336 有冰的帝君 400 redeem_reward batch_redeem_1_items 03-02 14:35:24
+ 8325 9336 有冰的帝君 700 redeem_reward batch_redeem_2_items 03-02 14:36:24
+ 8326 9336 有冰的帝君 120 redeem_reward batch_redeem_2_items 03-02 14:37:04
+ 8328 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-02 14:37:38
+ 8334 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 03-02 21:40:05
+ 8335 9336 有冰的帝君 150 redeem_reward batch_redeem_1_items 03-02 21:40:25
+ 8337 9336 有冰的帝君 2000 redeem_reward batch_redeem_4_items 03-02 21:41:59
+ 8339 9336 有冰的帝君 1400 redeem_reward batch_redeem_2_items 03-02 21:42:59
+ 8341 9336 有冰的帝君 1400 redeem_reward batch_redeem_2_items 03-02 21:44:42
+ 8343 9336 有冰的帝君 5200 redeem_reward batch_redeem_11_items 03-02 21:49:16
+ 8345 9336 有冰的帝君 9050 redeem_reward batch_redeem_16_items 03-02 21:54:33
+ 8347 9336 有冰的帝君 27700 redeem_reward batch_redeem_20_items 03-02 22:00:17
+ 8348 9336 有冰的帝君 600 redeem_reward batch_redeem_10_items 03-02 22:03:28
+ 8349 9336 有冰的帝君 300 redeem_reward batch_redeem_5_items 03-02 22:03:44
+ 8350 9336 有冰的帝君 180 redeem_reward batch_redeem_3_items 03-02 22:04:02
+ 8357 9336 有冰的帝君 28800 redeem_reward batch_redeem_1_items 03-02 22:41:40
+ 8360 9336 有冰的帝君 10100 redeem_reward batch_redeem_10_items 03-02 22:43:38
+ 8363 9336 有冰的帝君 38000 redeem_reward batch_redeem_1_items 03-02 22:44:14
+ 8368 9336 有冰的帝君 1500 redeem_reward batch_redeem_5_items 03-02 22:54:13
+ 8370 9336 有冰的帝君 1500 redeem_reward batch_redeem_4_items 03-02 22:55:54
+ 8371 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-02 22:56:50
+ 8373 9336 有冰的帝君 8100 redeem_reward batch_redeem_4_items 03-02 22:58:08
+ 8381 9336 有冰的帝君 16700 redeem_reward batch_redeem_2_items 03-02 23:15:20
+ 8382 9336 有冰的帝君 900 redeem_reward batch_redeem_3_items 03-02 23:19:32
+ 8383 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-02 23:19:47
+ 8384 9336 有冰的帝君 900 redeem_reward batch_redeem_3_items 03-02 23:20:06
+ 8387 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-02 23:37:33
+ 8388 9336 有冰的帝君 16700 redeem_reward batch_redeem_10_items 03-02 23:38:55
+ 8391 9336 有冰的帝君 4400 redeem_reward batch_redeem_10_items 03-02 23:43:50
+ 8392 9336 有冰的帝君 38000 redeem_reward batch_redeem_1_items 03-02 23:45:56
+ 8396 9336 有冰的帝君 5890 redeem_reward batch_redeem_1_items 03-02 23:59:49
+ 8397 9336 有冰的帝君 3000 redeem_reward batch_redeem_10_items 03-03 00:08:06
+ 8398 9336 有冰的帝君 9750 redeem_reward batch_redeem_10_items 03-03 00:08:25
+ 8399 9336 有冰的帝君 3000 redeem_reward batch_redeem_10_items 03-03 00:08:47
+ 8400 9336 有冰的帝君 11200 redeem_reward batch_redeem_10_items 03-03 00:09:13
+ 8403 9336 有冰的帝君 3300 redeem_reward batch_redeem_4_items 03-03 00:12:04
+ 8405 9336 有冰的帝君 2000 redeem_reward batch_redeem_6_items 03-03 00:12:45
+ 8407 9336 有冰的帝君 2800 redeem_reward batch_redeem_6_items 03-03 00:13:24
+ 8409 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-03 00:31:41
+ 8410 9336 有冰的帝君 650 redeem_reward batch_redeem_1_items 03-03 00:34:40
+ 8411 9336 有冰的帝君 2000 redeem_reward batch_redeem_1_items 03-03 00:35:39
+ 8412 9336 有冰的帝君 1800 redeem_reward batch_redeem_1_items 03-03 00:36:28
+ 8413 9336 有冰的帝君 1800 redeem_reward batch_redeem_1_items 03-03 00:37:14
+ 8415 9336 有冰的帝君 14900 redeem_reward batch_redeem_3_items 03-03 00:46:45
+ 8416 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-03 00:47:34
+ 8417 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-03 00:47:56
+ 8419 9336 有冰的帝君 16000 redeem_reward batch_redeem_1_items 03-03 01:02:05
+ 8420 9336 有冰的帝君 3050 redeem_reward batch_redeem_7_items 03-03 01:02:56
+ 8426 9336 有冰的帝君 6500 redeem_reward batch_redeem_20_items 03-03 02:20:31
+ 8427 9336 有冰的帝君 18300 redeem_reward batch_redeem_1_items 03-03 02:20:54
+ 8430 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 03-03 02:21:56
+ 8432 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 03-03 02:22:22
+ 8433 9336 有冰的帝君 54000 redeem_reward batch_redeem_2_items 03-03 02:23:34
+ 8438 9336 有冰的帝君 91950 redeem_reward batch_redeem_110_items 03-03 02:27:02
+ 8451 9336 有冰的帝君 5300 redeem_reward batch_redeem_13_items 03-03 02:36:10
+ 8453 9336 有冰的帝君 3500 redeem_reward batch_redeem_10_items 03-03 02:37:05
+ 8456 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-03 02:37:43
+ 8461 9336 有冰的帝君 6600 redeem_reward batch_redeem_18_items 03-03 02:39:25
+ 8463 9336 有冰的帝君 4600 redeem_reward batch_redeem_10_items 03-03 02:39:53
+ 8467 9336 有冰的帝君 4650 redeem_reward batch_redeem_10_items 03-03 02:40:27
+ 8469 9336 有冰的帝君 6500 redeem_reward batch_redeem_13_items 03-03 02:41:34
+ 8472 9336 有冰的帝君 4900 redeem_reward batch_redeem_10_items 03-03 02:42:05
+ 8475 9336 有冰的帝君 3400 redeem_reward batch_redeem_10_items 03-03 02:43:00
+ 8476 9336 有冰的帝君 500 redeem_reward batch_redeem_1_items 03-03 02:43:18
+ 8479 9336 有冰的帝君 3500 redeem_reward batch_redeem_10_items 03-03 02:43:41
+ 8482 9336 有冰的帝君 3600 redeem_reward batch_redeem_3_items 03-03 02:45:06
+ 8487 9336 有冰的帝君 8550 redeem_reward batch_redeem_2_items 03-03 02:46:44
+ 8489 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-03 02:47:28
+ 8491 9336 有冰的帝君 13900 redeem_reward batch_redeem_20_items 03-03 02:48:02
+ 8493 9336 有冰的帝君 58300 redeem_reward batch_redeem_20_items 03-03 02:49:53
+ 8503 9336 有冰的帝君 3600 redeem_reward batch_redeem_10_items 03-03 10:42:57
+ 8504 9336 有冰的帝君 2500 redeem_reward batch_redeem_2_items 03-03 10:59:41
+ 8507 9336 有冰的帝君 5100 redeem_reward batch_redeem_9_items 03-03 11:12:36
+ 8511 9336 有冰的帝君 3600 redeem_reward batch_redeem_60_items 03-03 11:40:18
+ 8513 9336 有冰的帝君 1500 redeem_reward batch_redeem_5_items 03-03 11:40:51
+ 8515 9336 有冰的帝君 1500 redeem_reward batch_redeem_5_items 03-03 11:41:27
+ 8517 9336 有冰的帝君 800 redeem_reward batch_redeem_2_items 03-03 11:41:59
+ 8519 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-03 11:42:24
+ 8521 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 03-03 11:43:00
+ 8528 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-03 21:43:47
+ 8530 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-03 21:44:24
+ 8532 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-03 21:44:55
+ 8533 9336 有冰的帝君 3350 redeem_reward batch_redeem_5_items 03-03 22:31:54
+ 8536 9336 有冰的帝君 14500 redeem_reward batch_redeem_6_items 03-03 22:33:54
+ 8537 9336 有冰的帝君 500 redeem_reward batch_redeem_1_items 03-03 22:35:41
+ 8538 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 03-03 22:36:57
+ 8539 9336 有冰的帝君 800 redeem_reward batch_redeem_1_items 03-03 22:37:27
+ 8540 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-03 22:37:57
+ 8541 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-03 22:38:41
+ 8544 9336 有冰的帝君 32900 redeem_reward batch_redeem_20_items 03-03 22:41:41
+ 8545 9336 有冰的帝君 2300 redeem_reward batch_redeem_1_items 03-03 22:42:34
+ 8552 9336 有冰的帝君 8950 redeem_reward batch_redeem_2_items 03-03 23:34:26
+ 8558 9336 有冰的帝君 40000 redeem_reward batch_redeem_1_items 03-03 23:49:53
+ 8560 9336 有冰的帝君 66850 redeem_reward batch_redeem_66_items 03-03 23:53:43
+ 8565 9336 有冰的帝君 78500 redeem_reward batch_redeem_1_items 03-04 00:21:14
+ 8567 9336 有冰的帝君 5000 redeem_reward batch_redeem_1_items 03-04 01:23:07
+ 8568 9336 有冰的帝君 38000 redeem_reward batch_redeem_1_items 03-04 01:28:08
+ 8571 9336 有冰的帝君 98000 redeem_reward batch_redeem_1_items 03-04 01:36:21
+ 8576 9336 有冰的帝君 45700 redeem_reward batch_redeem_6_items 03-04 02:09:02
+ 8584 9336 有冰的帝君 3950 redeem_reward batch_redeem_10_items 03-04 05:24:32
+ 8588 9336 有冰的帝君 31600 redeem_reward batch_redeem_3_items 03-04 07:50:39
+ 8590 9336 有冰的帝君 6500 redeem_reward batch_redeem_2_items 03-04 07:53:26
+ 8592 9336 有冰的帝君 1900 redeem_reward batch_redeem_5_items 03-04 07:55:43
+ 8594 9336 有冰的帝君 1500 redeem_reward batch_redeem_4_items 03-04 08:06:33
+ 8596 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-04 08:07:31
+ 8598 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-04 08:08:00
+ 8600 9336 有冰的帝君 21750 redeem_reward batch_redeem_60_items 03-04 08:09:30
+ 8601 9336 有冰的帝君 900 redeem_reward batch_redeem_3_items 03-04 08:27:19
+ 8602 9336 有冰的帝君 1000 redeem_reward batch_redeem_3_items 03-04 08:27:38
+ 8603 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-04 08:27:51
+ 8604 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-04 08:28:06
+ 8605 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-04 08:55:42
+ 8606 9336 有冰的帝君 60 redeem_reward batch_redeem_1_items 03-04 09:43:25
+ 8607 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-04 09:43:49
+ 8608 9336 有冰的帝君 1000 redeem_reward batch_redeem_1_items 03-04 09:44:46
+ 8610 9336 有冰的帝君 6300 redeem_reward batch_redeem_2_items 03-04 09:45:21
+ 8611 9336 有冰的帝君 1200 redeem_reward batch_redeem_3_items 03-04 10:02:51
+ 8613 9336 有冰的帝君 3150 redeem_reward batch_redeem_6_items 03-04 10:03:38
+ 8614 9336 有冰的帝君 900 redeem_reward batch_redeem_3_items 03-04 10:03:59
+ 8615 9336 有冰的帝君 1000 redeem_reward batch_redeem_1_items 03-04 10:06:55
+ 8632 9336 有冰的帝君 1200 redeem_reward batch_redeem_3_items 03-04 17:26:59
+ 8634 9336 有冰的帝君 900 redeem_reward batch_redeem_2_items 03-04 17:28:15
+ 8636 9336 有冰的帝君 1200 redeem_reward batch_redeem_3_items 03-04 17:28:40
+ 8638 9336 有冰的帝君 15800 redeem_reward batch_redeem_5_items 03-04 17:29:38
+ 8639 9336 有冰的帝君 500 redeem_reward batch_redeem_1_items 03-04 17:32:04
+ 8642 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-04 19:46:17
+ 8644 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-04 19:47:49
+ 8645 9336 有冰的帝君 2200 redeem_reward batch_redeem_5_items 03-04 20:26:11
+ 8647 9336 有冰的帝君 1200 redeem_reward batch_redeem_2_items 03-04 20:27:24
+ 8650 9336 有冰的帝君 1200 redeem_reward batch_redeem_2_items 03-04 20:28:21
+ 8652 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-04 20:29:03
+ 8654 9336 有冰的帝君 30000 redeem_reward batch_redeem_1_items 03-04 20:30:06
+ 8657 9336 有冰的帝君 20600 redeem_reward batch_redeem_20_items 03-04 20:50:54
+ 8659 9336 有冰的帝君 12200 redeem_reward batch_redeem_19_items 03-04 20:57:11
+ 8663 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-04 21:10:41
+ 8665 9336 有冰的帝君 13950 redeem_reward batch_redeem_18_items 03-04 21:12:06
+ 8676 9336 有冰的帝君 2100 redeem_reward batch_redeem_5_items 03-04 22:16:40
+ 8678 9336 有冰的帝君 9700 redeem_reward batch_redeem_6_items 03-04 22:17:34
+ 8680 9336 有冰的帝君 6700 redeem_reward batch_redeem_20_items 03-04 22:18:33
+ 8682 9336 有冰的帝君 10000 redeem_reward batch_redeem_13_items 03-04 22:19:09
+ 8685 9336 有冰的帝君 12260 redeem_reward batch_redeem_21_items 03-04 22:20:01
+ 8687 9336 有冰的帝君 4500 redeem_reward batch_redeem_5_items 03-04 22:23:28
+ 8688 9336 有冰的帝君 24500 redeem_reward batch_redeem_10_items 03-04 22:26:14
+ 8694 9336 有冰的帝君 66000 redeem_reward batch_redeem_2_items 03-04 22:31:39
+ 8698 9336 有冰的帝君 112500 redeem_reward batch_redeem_1_items 03-04 22:42:05
+ 8699 9336 有冰的帝君 12800 redeem_reward batch_redeem_1_items 03-04 22:42:23
+ 8703 9336 有冰的帝君 1900 redeem_reward batch_redeem_5_items 03-04 22:44:40
+ 8704 9336 有冰的帝君 900 redeem_reward batch_redeem_3_items 03-04 22:44:57
+ 8706 9336 有冰的帝君 900 redeem_reward batch_redeem_3_items 03-04 22:45:15
+ 8707 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-04 22:45:30
+ 8725 9336 有冰的帝君 2300 redeem_reward batch_redeem_7_items 03-04 23:15:46
+ 8728 9336 有冰的帝君 1500 redeem_reward batch_redeem_4_items 03-04 23:16:27
+ 8730 9336 有冰的帝君 1400 redeem_reward batch_redeem_4_items 03-04 23:17:12
+ 8731 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-05 00:02:25
+ 8733 9336 有冰的帝君 1800 redeem_reward batch_redeem_2_items 03-05 00:02:56
+ 8735 9336 有冰的帝君 1400 redeem_reward batch_redeem_4_items 03-05 00:03:40
+ 8737 9336 有冰的帝君 1700 redeem_reward batch_redeem_4_items 03-05 00:05:43
+ 8739 9336 有冰的帝君 2600 redeem_reward batch_redeem_4_items 03-05 00:07:12
+ 8741 9336 有冰的帝君 2000 redeem_reward batch_redeem_6_items 03-05 00:09:00
+ 8742 9336 有冰的帝君 1800 redeem_reward batch_redeem_1_items 03-05 00:10:11
+ 8744 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 03-05 00:11:33
+ 8745 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 03-05 00:12:02
+ 8747 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 03-05 00:12:59
+ 8749 9336 有冰的帝君 1250 redeem_reward batch_redeem_1_items 03-05 00:13:32
+ 8752 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 03-05 00:14:04
+ 8754 9336 有冰的帝君 300 redeem_reward batch_redeem_5_items 03-05 00:14:43
+ 8756 9336 有冰的帝君 300 redeem_reward batch_redeem_5_items 03-05 00:15:05
+ 8758 9336 有冰的帝君 300 redeem_reward batch_redeem_5_items 03-05 00:15:26
+ 8805 9336 有冰的帝君 7100 redeem_reward batch_redeem_4_items 03-05 12:29:59
+ 8810 9336 有冰的帝君 19100 redeem_reward batch_redeem_13_items 03-05 20:10:49
+ 8811 9336 有冰的帝君 60 redeem_reward batch_redeem_1_items 03-05 20:11:13
+ 8821 9336 有冰的帝君 8800 redeem_reward batch_redeem_18_items 03-05 21:15:59
+ 8823 9336 有冰的帝君 9400 redeem_reward batch_redeem_10_items 03-05 21:16:23
+ 8841 9336 有冰的帝君 900 redeem_reward batch_redeem_2_items 03-05 23:12:26
+ 8843 9336 有冰的帝君 700 redeem_reward batch_redeem_2_items 03-05 23:12:59
+ 8844 9336 有冰的帝君 42400 redeem_reward batch_redeem_20_items 03-05 23:19:00
+ 8846 9336 有冰的帝君 20600 redeem_reward batch_redeem_10_items 03-05 23:20:06
+ 8848 9336 有冰的帝君 12100 redeem_reward batch_redeem_11_items 03-05 23:21:01
+ 8858 9336 有冰的帝君 800 redeem_reward batch_redeem_2_items 03-06 06:08:31
+ 8860 9336 有冰的帝君 1300 redeem_reward batch_redeem_2_items 03-06 06:08:56
+ 8862 9336 有冰的帝君 1400 redeem_reward batch_redeem_4_items 03-06 06:09:31
+ 8864 9336 有冰的帝君 600 redeem_reward batch_redeem_2_items 03-06 06:50:26
+ 8866 9336 有冰的帝君 500 redeem_reward batch_redeem_1_items 03-06 06:50:43
+ 8868 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-06 06:51:26
+ 8870 9336 有冰的帝君 600 redeem_reward batch_redeem_1_items 03-06 06:51:59
+ 8872 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-06 06:52:29
+ 8874 9336 有冰的帝君 300 redeem_reward batch_redeem_1_items 03-06 06:53:11
+ 8897 9336 有冰的帝君 100 redeem_reward batch_redeem_1_items 03-07 02:14:57
+ 8916 9336 有冰的帝君 4000 redeem_reward batch_redeem_1_items 03-07 17:31:30
+ 8919 9336 有冰的帝君 11650 redeem_reward batch_redeem_10_items 03-07 17:38:52
+ 用户 9336 小计: 3090650 积分 (30906.50 元)
+
+ 7057 9365 未命名 1250 redeem_reward batch_redeem_1_items 02-19 22:48:37
+ 7098 9365 未命名 1250 redeem_reward batch_redeem_1_items 02-20 09:19:37
+ 7173 9365 未命名 7200 redeem_reward batch_redeem_1_items 02-20 23:13:03
+ 7203 9365 未命名 100 redeem_reward batch_redeem_1_items 02-20 23:48:32
+ 7514 9365 未命名 180 redeem_reward batch_redeem_3_items 02-21 22:05:14
+ 7515 9365 未命名 60 redeem_reward batch_redeem_1_items 02-21 22:06:28
+ 7516 9365 未命名 60 redeem_reward batch_redeem_1_items 02-21 22:07:25
+ 7517 9365 未命名 60 redeem_reward batch_redeem_1_items 02-21 22:08:25
+ 7522 9365 未命名 180 redeem_reward batch_redeem_3_items 02-21 22:10:20
+ 7528 9365 未命名 320 redeem_reward batch_redeem_3_items 02-21 22:13:15
+ 用户 9365 小计: 10660 积分 (106.60 元)
+
+ 8693 9449 古利特使出了佛怒火莲 2500 redeem_reward batch_redeem_7_items 03-04 22:30:30
+ 8695 9449 古利特使出了佛怒火莲 600 redeem_reward batch_redeem_2_items 03-04 22:35:23
+ 8724 9449 古利特使出了佛怒火莲 1750 redeem_reward batch_redeem_2_items 03-04 23:15:24
+ 8818 9449 古利特使出了佛怒火莲 600 redeem_reward batch_redeem_10_items 03-05 21:14:48
+ 8900 9449 古利特使出了佛怒火莲 600 redeem_reward batch_redeem_2_items 03-07 07:46:59
+ 用户 9449 小计: 6050 积分 (60.50 元)
+
+
+【五】并发漏洞证据 — 同一资产被多次转赠
+----------------------------------------------------------------------------------------------------
+ 资产ID 转赠次数 价值(元) 商品名称 转赠路径
+ -----------------------------------------------------------------------------------------------
+ 42746 4 375.00 MG 牛高达VER.KA 卡.. 9336→9116 | 9336→9116 | 9336→9116 | 9336→9116
+ 46668 4 375.00 MG 牛高达VER.KA 卡.. 9210→9116 | 9210→9116 | 9210→9116 | 9210→9116
+ 51038 3 605.00 PB限定 MG 红龙形态红龙.. 9210→9116 | 9116→9210 | 9210→9116
+ 43304 3 375.00 MG 牛高达VER.KA 卡.. 9305→9116 | 9116→9305 | 9305→9116
+ 44152 3 375.00 MG 牛高达VER.KA 卡.. 9248→9116 | 9248→9116 | 9248→9116
+ 46445 3 375.00 MG 牛高达VER.KA 卡.. 9230→9116 | 9230→9116 | 9230→9116
+ 46667 3 375.00 MG 牛高达VER.KA 卡.. 9210→9116 | 9210→9116 | 9210→9116
+ 46506 2 375.00 MG 牛高达VER.KA 卡.. 9209→9116 | 9209→9116
+ 46666 2 375.00 MG 牛高达VER.KA 卡.. 9210→9116 | 9210→9116
+ 46669 2 375.00 MG 牛高达VER.KA 卡.. 9210→9116 | 9210→9116
+ 46672 2 375.00 MG 牛高达VER.KA 卡.. 9210→9116 | 9210→9116
+ 46673 2 375.00 MG 牛高达VER.KA 卡.. 9210→9116 | 9210→9116
+ 46686 2 375.00 MG 牛高达VER.KA 卡.. 9210→9116 | 9210→9116
+
+ 共 13 个资产被多次转赠(并发漏洞证据)
+
+
+【六】转赠关系网络汇总
+----------------------------------------------------------------------------------------------------
+ 赠送方 → 接收方 转赠次 资产数 总价值(元) 首次转赠 末次转赠
+ ------------------------------------------------------------------------------------------------------------------------
+ 9210(非酋) → 9116(非洲人) 43 32 16670.00 02-21 23:49 03-03 00:04
+ 9222(嗯?!!!!) → 9116(非洲人) 9 9 4655.00 02-17 11:38 02-21 15:12
+ 9336(有冰的帝君) → 9110(极品官方内部号) 3 3 3710.00 02-24 01:23 02-28 20:00
+ 9248(不出last退了) → 9116(非洲人) 7 5 3565.00 02-22 23:46 03-01 00:04
+ 9138(卷卷大魔王) → 9116(非洲人) 2 2 3130.00 03-02 23:11 03-02 23:11
+ 9336(有冰的帝君) → 9116(非洲人) 7 4 2950.00 02-21 14:53 03-04 02:36
+ 9209(程c) → 9116(非洲人) 5 4 1875.00 02-21 16:49 02-21 16:52
+ 9230(巨欧小肥龙) → 9116(非洲人) 5 3 1875.00 02-21 16:43 02-21 16:47
+ 9305(新人) → 9116(非洲人) 3 2 1650.00 02-19 02:18 02-28 20:15
+ 9199(欣喜的罗马里奥) → 9116(非洲人) 3 3 1058.00 03-05 19:40 03-05 19:41
+ 9116(非洲人) → 9305(新人) 2 2 750.00 02-19 02:24 02-21 01:16
+ 9116(非洲人) → 9210(非酋) 3 3 623.50 02-23 19:39 03-02 14:06
+ 9222(嗯?!!!!) → 9347(约翰在武汉看电影) 1 1 420.00 02-26 16:02 02-26 16:02
+ 9113(盖德·穆勒大力出..) → 9110(极品官方内部号) 17 17 418.50 01-24 22:59 03-05 22:21
+ 9111(嘟嘟) → 9210(非酋) 1 1 320.00 03-03 11:27 03-03 11:27
+ 9110(极品官方内部号) → 9160(肖申克在武汉看电..) 1 1 175.00 02-04 01:01 02-04 01:01
+ 9230(巨欧小肥龙) → 9209(程c) 2 2 124.00 02-28 01:25 02-28 01:25
+ 9330(拼搏的内马尔) → 9094(范巴斯滕救了一个..) 3 3 113.90 02-20 22:13 02-27 18:01
+ 9280(诚心的肯尼) → 9222(嗯?!!!!) 8 8 84.50 02-17 23:37 02-17 23:41
+ 9347(约翰在武汉看电影) → 9222(嗯?!!!!) 5 5 79.50 02-19 01:12 02-19 01:38
+ 9110(极品官方内部号) → 9116(非洲人) 1 1 79.00 02-19 02:53 02-19 02:53
+ 9110(极品官方内部号) → 9209(程c) 2 2 63.00 02-28 02:09 02-28 02:09
+ 9111(嘟嘟) → 9336(有冰的帝君) 1 1 60.00 03-03 00:42 03-03 00:42
+ 9336(有冰的帝君) → 9446(弗兰科望穿秋水) 1 1 29.00 03-03 11:03 03-03 11:03
+ 9116(非洲人) → 9209(程c) 1 1 21.00 02-27 14:31 02-27 14:31
+ 9110(极品官方内部号) → 9222(嗯?!!!!) 2 2 16.00 02-17 23:52 02-17 23:52
+ 9094(范巴斯滕救了一个..) → 9449(古利特使出了佛怒..) 1 1 12.50 03-04 22:34 03-04 22:34
+ 9210(非酋) → 9209(程c) 4 4 12.00 02-28 01:46 02-28 01:48
+ 9116(非洲人) → 9110(极品官方内部号) 4 4 10.50 02-25 18:08 02-25 18:32
+ 9116(非洲人) → 9248(不出last退了) 2 2 8.00 02-19 13:26 02-19 13:27
+ 9209(程c) → 9210(非酋) 1 1 4.00 02-24 21:22 02-24 21:22
+ 9117(小叶) → 9116(非洲人) 2 2 3.00 03-03 02:32 03-03 02:32
+ 9209(程c) → 9110(极品官方内部号) 2 2 2.60 02-17 23:53 02-26 03:02
+ 9110(极品官方内部号) → 9365(未命名) 1 1 1.00 02-20 23:37 02-20 23:37
+ 9209(程c) → 9230(巨欧小肥龙) 1 1 0.60 02-21 00:21 02-21 00:21
+ 9359(雅典娜心花怒放) → 9248(不出last退了) 1 1 0.60 03-03 12:14 03-03 12:14
+
+
+【七】用户积分余额 vs 薅取金额对比
+------------------------------------------------------------------------------------------
+ 用户ID 昵称 薅取积分 薅取金额(元) 当前余额 可扣回?
+ -------------------------------------------------------------------------------------
+ 9116 非洲人 1073700 10737.00 340 ⚠️ 仅可扣 340
+ 9305 新人 75000 750.00 80 ⚠️ 仅可扣 80
+ 9110 极品官方内部号 44660 446.60 11030 ⚠️ 仅可扣 11030
+ 9209 程c 22000 220.00 39260 ✅ 可全额扣回
+ 9222 嗯?!!!! 18000 180.00 580 ⚠️ 仅可扣 580
+ 9336 有冰的帝君 6000 60.00 10770 ✅ 可全额扣回
+ 9094 范巴斯滕救了一个美女 2500 25.00 160 ⚠️ 仅可扣 160
+ 9210 非酋 2250 22.50 190 ⚠️ 仅可扣 190
+ 9449 古利特使出了佛怒火莲 1250 12.50 1550 ✅ 可全额扣回
+ 9248 不出last退了 860 8.60 53190 ✅ 可全额扣回
+ 9365 未命名 100 1.00 10 ⚠️ 仅可扣 10
+ 9230 巨欧小肥龙 60 0.60 80 ✅ 可全额扣回
+
+========================================================================================================================
+ 报告结束
+========================================================================================================================
diff --git a/internal/api/activity/issue_choices_app.go b/internal/api/activity/issue_choices_app.go
index f5c1fbb..4bcfb76 100755
--- a/internal/api/activity/issue_choices_app.go
+++ b/internal/api/activity/issue_choices_app.go
@@ -1,11 +1,12 @@
package app
import (
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
"fmt"
"net/http"
"strconv"
+
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
)
type listIssueChoicesResponse struct {
diff --git a/internal/api/activity/lottery_app.go b/internal/api/activity/lottery_app.go
index 5fad912..b78d512 100755
--- a/internal/api/activity/lottery_app.go
+++ b/internal/api/activity/lottery_app.go
@@ -1,11 +1,6 @@
package app
import (
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- "bindbox-game/internal/pkg/validation"
- "bindbox-game/internal/repository/mysql/dao"
- "bindbox-game/internal/repository/mysql/model"
"context"
"crypto/hmac"
"crypto/sha256"
@@ -17,6 +12,11 @@ import (
"net/http"
"time"
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ "bindbox-game/internal/pkg/validation"
+ "bindbox-game/internal/repository/mysql/dao"
+ "bindbox-game/internal/repository/mysql/model"
titlesvc "bindbox-game/internal/service/title"
"gorm.io/gorm/clause"
diff --git a/internal/api/activity/lottery_helper.go b/internal/api/activity/lottery_helper.go
index 517812b..c25568a 100755
--- a/internal/api/activity/lottery_helper.go
+++ b/internal/api/activity/lottery_helper.go
@@ -1,11 +1,12 @@
package app
import (
+ "fmt"
+ "time"
+
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/pkg/util/remark"
"bindbox-game/internal/repository/mysql/model"
- "fmt"
- "time"
)
// couponJoinResult 优惠券联合查询结果
diff --git a/internal/api/activity/lottery_result_order_app.go b/internal/api/activity/lottery_result_order_app.go
index 7f4b4fc..32e18bb 100755
--- a/internal/api/activity/lottery_result_order_app.go
+++ b/internal/api/activity/lottery_result_order_app.go
@@ -1,11 +1,6 @@
package app
import (
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- "bindbox-game/internal/pkg/util/remark"
- "bindbox-game/internal/pkg/validation"
- "bindbox-game/internal/repository/mysql/model"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
@@ -13,6 +8,12 @@ import (
"encoding/json"
"strings"
"time"
+
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ "bindbox-game/internal/pkg/util/remark"
+ "bindbox-game/internal/pkg/validation"
+ "bindbox-game/internal/repository/mysql/model"
)
type orderResultQuery struct {
diff --git a/internal/api/activity/matching_game_app.go b/internal/api/activity/matching_game_app.go
index 65884eb..900d055 100755
--- a/internal/api/activity/matching_game_app.go
+++ b/internal/api/activity/matching_game_app.go
@@ -1,13 +1,6 @@
package app
import (
- "bindbox-game/configs"
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- "bindbox-game/internal/pkg/validation"
- "bindbox-game/internal/pkg/wechat"
- "bindbox-game/internal/repository/mysql/model"
- activitysvc "bindbox-game/internal/service/activity"
"context"
"crypto/rand"
"encoding/binary"
@@ -18,6 +11,14 @@ import (
"sort"
"time"
+ "bindbox-game/configs"
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ "bindbox-game/internal/pkg/validation"
+ "bindbox-game/internal/pkg/wechat"
+ "bindbox-game/internal/repository/mysql/model"
+ activitysvc "bindbox-game/internal/service/activity"
+
"github.com/redis/go-redis/v9"
"go.uber.org/zap"
)
diff --git a/internal/api/activity/matching_game_app_test.go b/internal/api/activity/matching_game_app_test.go
index ac277ac..dcd1606 100755
--- a/internal/api/activity/matching_game_app_test.go
+++ b/internal/api/activity/matching_game_app_test.go
@@ -1,8 +1,9 @@
package app
import (
- "bindbox-game/internal/repository/mysql/model"
"testing"
+
+ "bindbox-game/internal/repository/mysql/model"
)
// TestSelectRewardExact 测试对对碰选奖逻辑:精确匹配 TotalPairs == MinScore
diff --git a/internal/api/activity/matching_game_helper.go b/internal/api/activity/matching_game_helper.go
index e820eb5..2c01375 100755
--- a/internal/api/activity/matching_game_helper.go
+++ b/internal/api/activity/matching_game_helper.go
@@ -1,17 +1,18 @@
package app
import (
- "bindbox-game/configs"
- "bindbox-game/internal/pkg/wechat"
- "bindbox-game/internal/repository/mysql/model"
- activitysvc "bindbox-game/internal/service/activity"
- usersvc "bindbox-game/internal/service/user"
"context"
"fmt"
"strings"
"sync"
"time"
+ "bindbox-game/configs"
+ "bindbox-game/internal/pkg/wechat"
+ "bindbox-game/internal/repository/mysql/model"
+ activitysvc "bindbox-game/internal/service/activity"
+ usersvc "bindbox-game/internal/service/user"
+
"go.uber.org/zap"
)
diff --git a/internal/api/admin/activity_commitment_admin.go b/internal/api/admin/activity_commitment_admin.go
index 4482ce2..0441a47 100755
--- a/internal/api/admin/activity_commitment_admin.go
+++ b/internal/api/admin/activity_commitment_admin.go
@@ -1,12 +1,13 @@
package admin
import (
+ "net/http"
+ "strconv"
+
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/repository/mysql/dao"
activitysvc "bindbox-game/internal/service/activity"
- "net/http"
- "strconv"
)
type activityCommitGenerateResp struct {
diff --git a/internal/api/admin/auth_refresh.go b/internal/api/admin/auth_refresh.go
index 7a71199..89b865c 100755
--- a/internal/api/admin/auth_refresh.go
+++ b/internal/api/admin/auth_refresh.go
@@ -1,19 +1,19 @@
package admin
import (
- "net/http"
- "time"
+ "net/http"
+ "time"
- "bindbox-game/configs"
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- "bindbox-game/internal/pkg/jwtoken"
- "bindbox-game/internal/pkg/utils"
+ "bindbox-game/configs"
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ "bindbox-game/internal/pkg/jwtoken"
+ "bindbox-game/internal/pkg/utils"
)
type refreshResponse struct {
- Token string `json:"token"`
- ExpiresIn int64 `json:"expires_in"`
+ Token string `json:"token"`
+ ExpiresIn int64 `json:"expires_in"`
}
// RefreshToken 刷新管理员访问令牌
@@ -26,25 +26,25 @@ type refreshResponse struct {
// @Router /api/admin/auth/refresh [post]
// @Security LoginVerifyToken
func (h *handler) RefreshToken() core.HandlerFunc {
- return func(ctx core.Context) {
- auth := ctx.Request().Header.Get("Authorization")
- if auth == "" {
- ctx.AbortWithError(core.Error(http.StatusUnauthorized, code.AdminLoginError, "未携带令牌"))
- return
- }
- newToken, err := jwtoken.New(configs.Get().JWT.AdminSecret).Refresh(auth)
- if err != nil || newToken == "" {
- ctx.AbortWithError(core.Error(http.StatusUnauthorized, code.AdminLoginError, "令牌刷新失败"))
- return
- }
- info := ctx.SessionUserInfo()
- if info.Id > 0 {
- _, _ = h.writeDB.Admin.WithContext(ctx.RequestContext()).Where(h.writeDB.Admin.ID.Eq(int32(info.Id))).Updates(map[string]any{
- "last_login_time": time.Now(),
- "last_login_ip": utils.GetIP(ctx.Request()),
- "last_login_hash": utils.MD5(newToken),
- })
- }
- ctx.Payload(refreshResponse{Token: newToken, ExpiresIn: int64(24 * 3600)})
- }
-}
\ No newline at end of file
+ return func(ctx core.Context) {
+ auth := ctx.Request().Header.Get("Authorization")
+ if auth == "" {
+ ctx.AbortWithError(core.Error(http.StatusUnauthorized, code.AdminLoginError, "未携带令牌"))
+ return
+ }
+ newToken, err := jwtoken.New(configs.Get().JWT.AdminSecret).Refresh(auth)
+ if err != nil || newToken == "" {
+ ctx.AbortWithError(core.Error(http.StatusUnauthorized, code.AdminLoginError, "令牌刷新失败"))
+ return
+ }
+ info := ctx.SessionUserInfo()
+ if info.Id > 0 {
+ _, _ = h.writeDB.Admin.WithContext(ctx.RequestContext()).Where(h.writeDB.Admin.ID.Eq(int32(info.Id))).Updates(map[string]any{
+ "last_login_time": time.Now(),
+ "last_login_ip": utils.GetIP(ctx.Request()),
+ "last_login_hash": utils.MD5(newToken),
+ })
+ }
+ ctx.Payload(refreshResponse{Token: newToken, ExpiresIn: int64(24 * 3600)})
+ }
+}
diff --git a/internal/api/admin/banner.go b/internal/api/admin/banner.go
index e8d4f01..e9730e0 100755
--- a/internal/api/admin/banner.go
+++ b/internal/api/admin/banner.go
@@ -1,26 +1,26 @@
package admin
import (
- "net/http"
- "strconv"
+ "net/http"
+ "strconv"
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- "bindbox-game/internal/pkg/validation"
- bannersvc "bindbox-game/internal/service/banner"
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ "bindbox-game/internal/pkg/validation"
+ bannersvc "bindbox-game/internal/service/banner"
)
type createBannerRequest struct {
- Title string `json:"title" binding:"required"`
- ImageURL string `json:"image_url" binding:"required"`
- LinkURL string `json:"link_url"`
- Sort int32 `json:"sort"`
- Status int32 `json:"status"`
+ Title string `json:"title" binding:"required"`
+ ImageURL string `json:"image_url" binding:"required"`
+ LinkURL string `json:"link_url"`
+ Sort int32 `json:"sort"`
+ Status int32 `json:"status"`
}
type createBannerResponse struct {
- ID int64 `json:"id"`
- Message string `json:"message"`
+ ID int64 `json:"id"`
+ Message string `json:"message"`
}
// CreateBanner 创建轮播图
@@ -34,34 +34,34 @@ type createBannerResponse struct {
// @Router /api/admin/banners [post]
// @Security LoginVerifyToken
func (h *handler) CreateBanner() core.HandlerFunc {
- return func(ctx core.Context) {
- req := new(createBannerRequest)
- res := new(createBannerResponse)
- if err := ctx.ShouldBindJSON(req); err != nil {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
- return
- }
- if ctx.SessionUserInfo().IsSuper != 1 {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
- return
- }
- item, err := h.banner.Create(ctx.RequestContext(), bannersvc.CreateInput{Title: req.Title, ImageURL: req.ImageURL, LinkURL: req.LinkURL, Sort: req.Sort, Status: req.Status})
- if err != nil {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
- return
- }
- res.ID = item.ID
- res.Message = "操作成功"
- ctx.Payload(res)
- }
+ return func(ctx core.Context) {
+ req := new(createBannerRequest)
+ res := new(createBannerResponse)
+ if err := ctx.ShouldBindJSON(req); err != nil {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
+ return
+ }
+ if ctx.SessionUserInfo().IsSuper != 1 {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
+ return
+ }
+ item, err := h.banner.Create(ctx.RequestContext(), bannersvc.CreateInput{Title: req.Title, ImageURL: req.ImageURL, LinkURL: req.LinkURL, Sort: req.Sort, Status: req.Status})
+ if err != nil {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
+ return
+ }
+ res.ID = item.ID
+ res.Message = "操作成功"
+ ctx.Payload(res)
+ }
}
type modifyBannerRequest struct {
- Title *string `json:"title"`
- ImageURL *string `json:"image_url"`
- LinkURL *string `json:"link_url"`
- Sort *int32 `json:"sort"`
- Status *int32 `json:"status"`
+ Title *string `json:"title"`
+ ImageURL *string `json:"image_url"`
+ LinkURL *string `json:"link_url"`
+ Sort *int32 `json:"sort"`
+ Status *int32 `json:"status"`
}
// ModifyBanner 修改轮播图
@@ -76,24 +76,24 @@ type modifyBannerRequest struct {
// @Router /api/admin/banners/{banner_id} [put]
// @Security LoginVerifyToken
func (h *handler) ModifyBanner() core.HandlerFunc {
- return func(ctx core.Context) {
- req := new(modifyBannerRequest)
- if err := ctx.ShouldBindJSON(req); err != nil {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
- return
- }
- idStr := ctx.Param("banner_id")
- id, _ := strconv.ParseInt(idStr, 10, 64)
- if ctx.SessionUserInfo().IsSuper != 1 {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
- return
- }
- if err := h.banner.Modify(ctx.RequestContext(), id, bannersvc.ModifyInput{Title: req.Title, ImageURL: req.ImageURL, LinkURL: req.LinkURL, Sort: req.Sort, Status: req.Status}); err != nil {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
- return
- }
- ctx.Payload(pcSimpleMessage{Message: "操作成功"})
- }
+ return func(ctx core.Context) {
+ req := new(modifyBannerRequest)
+ if err := ctx.ShouldBindJSON(req); err != nil {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
+ return
+ }
+ idStr := ctx.Param("banner_id")
+ id, _ := strconv.ParseInt(idStr, 10, 64)
+ if ctx.SessionUserInfo().IsSuper != 1 {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
+ return
+ }
+ if err := h.banner.Modify(ctx.RequestContext(), id, bannersvc.ModifyInput{Title: req.Title, ImageURL: req.ImageURL, LinkURL: req.LinkURL, Sort: req.Sort, Status: req.Status}); err != nil {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
+ return
+ }
+ ctx.Payload(pcSimpleMessage{Message: "操作成功"})
+ }
}
// DeleteBanner 删除轮播图
@@ -107,41 +107,41 @@ func (h *handler) ModifyBanner() core.HandlerFunc {
// @Router /api/admin/banners/{banner_id} [delete]
// @Security LoginVerifyToken
func (h *handler) DeleteBanner() core.HandlerFunc {
- return func(ctx core.Context) {
- idStr := ctx.Param("banner_id")
- id, _ := strconv.ParseInt(idStr, 10, 64)
- if ctx.SessionUserInfo().IsSuper != 1 {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
- return
- }
- if err := h.banner.Delete(ctx.RequestContext(), id); err != nil {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
- return
- }
- ctx.Payload(pcSimpleMessage{Message: "操作成功"})
- }
+ return func(ctx core.Context) {
+ idStr := ctx.Param("banner_id")
+ id, _ := strconv.ParseInt(idStr, 10, 64)
+ if ctx.SessionUserInfo().IsSuper != 1 {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
+ return
+ }
+ if err := h.banner.Delete(ctx.RequestContext(), id); err != nil {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
+ return
+ }
+ ctx.Payload(pcSimpleMessage{Message: "操作成功"})
+ }
}
type listBannersRequest struct {
- Status *int32 `form:"status"`
- Page int `form:"page"`
- PageSize int `form:"page_size"`
+ Status *int32 `form:"status"`
+ Page int `form:"page"`
+ PageSize int `form:"page_size"`
}
type bannerItem struct {
- ID int64 `json:"id"`
- Title string `json:"title"`
- ImageURL string `json:"image_url"`
- LinkURL string `json:"link_url"`
- Sort int32 `json:"sort"`
- Status int32 `json:"status"`
+ ID int64 `json:"id"`
+ Title string `json:"title"`
+ ImageURL string `json:"image_url"`
+ LinkURL string `json:"link_url"`
+ Sort int32 `json:"sort"`
+ Status int32 `json:"status"`
}
type listBannersResponse struct {
- Page int `json:"page"`
- PageSize int `json:"page_size"`
- Total int64 `json:"total"`
- List []bannerItem `json:"list"`
+ Page int `json:"page"`
+ PageSize int `json:"page_size"`
+ Total int64 `json:"total"`
+ List []bannerItem `json:"list"`
}
// ListBanners 查看轮播图列表
@@ -157,25 +157,25 @@ type listBannersResponse struct {
// @Router /api/admin/banners [get]
// @Security LoginVerifyToken
func (h *handler) ListBanners() core.HandlerFunc {
- return func(ctx core.Context) {
- req := new(listBannersRequest)
- res := new(listBannersResponse)
- if err := ctx.ShouldBindForm(req); err != nil {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
- return
- }
- items, total, err := h.banner.List(ctx.RequestContext(), bannersvc.ListInput{Status: req.Status, Page: req.Page, PageSize: req.PageSize})
- if err != nil {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
- return
- }
- res.Page = req.Page
- res.PageSize = req.PageSize
- res.Total = total
- res.List = make([]bannerItem, len(items))
- for i, it := range items {
- res.List[i] = bannerItem{ID: it.ID, Title: it.Title, ImageURL: it.ImageURL, LinkURL: it.LinkURL, Sort: it.Sort, Status: it.Status}
- }
- ctx.Payload(res)
- }
-}
\ No newline at end of file
+ return func(ctx core.Context) {
+ req := new(listBannersRequest)
+ res := new(listBannersResponse)
+ if err := ctx.ShouldBindForm(req); err != nil {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
+ return
+ }
+ items, total, err := h.banner.List(ctx.RequestContext(), bannersvc.ListInput{Status: req.Status, Page: req.Page, PageSize: req.PageSize})
+ if err != nil {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
+ return
+ }
+ res.Page = req.Page
+ res.PageSize = req.PageSize
+ res.Total = total
+ res.List = make([]bannerItem, len(items))
+ for i, it := range items {
+ res.List[i] = bannerItem{ID: it.ID, Title: it.Title, ImageURL: it.ImageURL, LinkURL: it.LinkURL, Sort: it.Sort, Status: it.Status}
+ }
+ ctx.Payload(res)
+ }
+}
diff --git a/internal/api/admin/dashboard_activity.go b/internal/api/admin/dashboard_activity.go
index 83f685e..dd0e922 100755
--- a/internal/api/admin/dashboard_activity.go
+++ b/internal/api/admin/dashboard_activity.go
@@ -1,11 +1,6 @@
package admin
import (
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- "bindbox-game/internal/pkg/validation"
- "bindbox-game/internal/repository/mysql/model"
- financesvc "bindbox-game/internal/service/finance"
"encoding/json"
"fmt"
"net/http"
@@ -14,6 +9,12 @@ import (
"strings"
"time"
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ "bindbox-game/internal/pkg/validation"
+ "bindbox-game/internal/repository/mysql/model"
+ financesvc "bindbox-game/internal/service/finance"
+
"gorm.io/gorm"
)
diff --git a/internal/api/admin/dashboard_spending.go b/internal/api/admin/dashboard_spending.go
index eafac06..ae9883b 100755
--- a/internal/api/admin/dashboard_spending.go
+++ b/internal/api/admin/dashboard_spending.go
@@ -1,16 +1,17 @@
package admin
import (
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- "bindbox-game/internal/pkg/validation"
- "bindbox-game/internal/repository/mysql/model"
- financesvc "bindbox-game/internal/service/finance"
"fmt"
"net/http"
"sort"
"strings"
"time"
+
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ "bindbox-game/internal/pkg/validation"
+ "bindbox-game/internal/repository/mysql/model"
+ financesvc "bindbox-game/internal/service/finance"
)
type spendingLeaderboardRequest struct {
diff --git a/internal/api/admin/douyin_orders_admin.go b/internal/api/admin/douyin_orders_admin.go
index cb6d05b..896335a 100755
--- a/internal/api/admin/douyin_orders_admin.go
+++ b/internal/api/admin/douyin_orders_admin.go
@@ -1,10 +1,6 @@
package admin
import (
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- "bindbox-game/internal/pkg/validation"
- "bindbox-game/internal/service/douyin"
"context"
"errors"
"fmt"
@@ -13,6 +9,11 @@ import (
"strconv"
"strings"
"time"
+
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ "bindbox-game/internal/pkg/validation"
+ "bindbox-game/internal/service/douyin"
)
// ---------- 抖店配置 API ----------
diff --git a/internal/api/admin/ichiban_slots_admin.go b/internal/api/admin/ichiban_slots_admin.go
index 67379cd..5163221 100755
--- a/internal/api/admin/ichiban_slots_admin.go
+++ b/internal/api/admin/ichiban_slots_admin.go
@@ -1,12 +1,13 @@
package admin
import (
+ "net/http"
+ "strconv"
+
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/repository/mysql/dao"
activitysvc "bindbox-game/internal/service/activity"
- "net/http"
- "strconv"
)
type listSlotsRequest struct {
diff --git a/internal/api/admin/issues_admin.go b/internal/api/admin/issues_admin.go
index 09cf176..4435b11 100755
--- a/internal/api/admin/issues_admin.go
+++ b/internal/api/admin/issues_admin.go
@@ -23,11 +23,11 @@ type listIssuesResponse struct {
}
type activitysvcIssueData struct {
- ID int64 `json:"id"`
- IssueNumber string `json:"issue_number"`
- Status int32 `json:"status"`
- Sort int32 `json:"sort"`
- PrizeCount int64 `json:"prize_count"`
+ ID int64 `json:"id"`
+ IssueNumber string `json:"issue_number"`
+ Status int32 `json:"status"`
+ Sort int32 `json:"sort"`
+ PrizeCount int64 `json:"prize_count"`
}
// ListActivityIssues 查看活动期数
@@ -70,21 +70,21 @@ func (h *handler) ListActivityIssues() core.HandlerFunc {
res.Page = req.Page
res.PageSize = req.PageSize
res.Total = total
- res.List = make([]*activitysvcIssueData, len(items))
- for i, v := range items {
- var prizeCount int64
- count, err := h.readDB.ActivityRewardSettings.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.ActivityRewardSettings.IssueID.Eq(v.ID)).Count()
- if err == nil {
- prizeCount = count
- }
- res.List[i] = &activitysvcIssueData{
- ID: v.ID,
- IssueNumber: v.IssueNumber,
- Status: v.Status,
- Sort: v.Sort,
- PrizeCount: prizeCount,
- }
- }
+ res.List = make([]*activitysvcIssueData, len(items))
+ for i, v := range items {
+ var prizeCount int64
+ count, err := h.readDB.ActivityRewardSettings.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.ActivityRewardSettings.IssueID.Eq(v.ID)).Count()
+ if err == nil {
+ prizeCount = count
+ }
+ res.List[i] = &activitysvcIssueData{
+ ID: v.ID,
+ IssueNumber: v.IssueNumber,
+ Status: v.Status,
+ Sort: v.Sort,
+ PrizeCount: prizeCount,
+ }
+ }
ctx.Payload(res)
}
}
diff --git a/internal/api/admin/item_cards_admin.go b/internal/api/admin/item_cards_admin.go
index 278f6e4..de50537 100755
--- a/internal/api/admin/item_cards_admin.go
+++ b/internal/api/admin/item_cards_admin.go
@@ -230,21 +230,21 @@ func (h *handler) ModifySystemItemCard() core.HandlerFunc {
// @Failure 500 {object} code.Failure "服务器内部错误"
// @Router /api/admin/system_item_cards/{item_card_id} [delete]
func (h *handler) DeleteSystemItemCard() core.HandlerFunc {
- return func(ctx core.Context) {
- idStr := ctx.Param("item_card_id")
- id, _ := strconv.ParseInt(idStr, 10, 64)
- if ctx.SessionUserInfo().IsSuper != 1 {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
- return
- }
- uid := int64(ctx.SessionUserInfo().Id)
- set := map[string]any{"deleted_at": time.Now(), "deleted_by": uid}
- if _, err := h.writeDB.SystemItemCards.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemItemCards.ID.Eq(id)).Updates(set); err != nil {
- ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
- return
- }
- ctx.Payload(simpleMessageResponse{Message: "操作成功"})
- }
+ return func(ctx core.Context) {
+ idStr := ctx.Param("item_card_id")
+ id, _ := strconv.ParseInt(idStr, 10, 64)
+ if ctx.SessionUserInfo().IsSuper != 1 {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
+ return
+ }
+ uid := int64(ctx.SessionUserInfo().Id)
+ set := map[string]any{"deleted_at": time.Now(), "deleted_by": uid}
+ if _, err := h.writeDB.SystemItemCards.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemItemCards.ID.Eq(id)).Updates(set); err != nil {
+ ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
+ return
+ }
+ ctx.Payload(simpleMessageResponse{Message: "操作成功"})
+ }
}
type listItemCardsRequest struct {
@@ -257,25 +257,25 @@ type listItemCardsRequest struct {
}
type itemCardListItem struct {
- ID int64 `json:"id"`
- CreatedAt time.Time `json:"created_at"`
- UpdatedAt time.Time `json:"updated_at"`
- Name string `json:"name"`
- Status int32 `json:"status"`
- CardType int32 `json:"card_type"`
- ScopeType int32 `json:"scope_type"`
- ActivityCategoryID int64 `json:"activity_category_id"`
- ActivityID int64 `json:"activity_id"`
- IssueID int64 `json:"issue_id"`
- Price int64 `json:"price"`
- ValidStart time.Time `json:"valid_start"`
- ValidEnd time.Time `json:"valid_end"`
- EffectType int32 `json:"effect_type"`
- RewardMultiplierX1000 int32 `json:"reward_multiplier_x1000"`
- BoostRateX1000 int32 `json:"boost_rate_x1000"`
- StackingStrategy int32 `json:"stacking_strategy"`
- MaxEffectValueX1000 int32 `json:"max_effect_value_x1000"`
- Remark string `json:"remark"`
+ ID int64 `json:"id"`
+ CreatedAt time.Time `json:"created_at"`
+ UpdatedAt time.Time `json:"updated_at"`
+ Name string `json:"name"`
+ Status int32 `json:"status"`
+ CardType int32 `json:"card_type"`
+ ScopeType int32 `json:"scope_type"`
+ ActivityCategoryID int64 `json:"activity_category_id"`
+ ActivityID int64 `json:"activity_id"`
+ IssueID int64 `json:"issue_id"`
+ Price int64 `json:"price"`
+ ValidStart time.Time `json:"valid_start"`
+ ValidEnd time.Time `json:"valid_end"`
+ EffectType int32 `json:"effect_type"`
+ RewardMultiplierX1000 int32 `json:"reward_multiplier_x1000"`
+ BoostRateX1000 int32 `json:"boost_rate_x1000"`
+ StackingStrategy int32 `json:"stacking_strategy"`
+ MaxEffectValueX1000 int32 `json:"max_effect_value_x1000"`
+ Remark string `json:"remark"`
}
type listItemCardsResponse struct {
@@ -345,30 +345,30 @@ func (h *handler) ListSystemItemCards() core.HandlerFunc {
res.Page = req.Page
res.PageSize = req.PageSize
res.Total = total
- res.List = make([]itemCardListItem, len(rows))
- for i, r := range rows {
- res.List[i] = itemCardListItem{
- ID: r.ID,
- CreatedAt: r.CreatedAt,
- UpdatedAt: r.UpdatedAt,
- Name: r.Name,
- Status: r.Status,
- CardType: r.CardType,
- ScopeType: r.ScopeType,
- ActivityCategoryID: r.ActivityCategoryID,
- ActivityID: r.ActivityID,
- IssueID: r.IssueID,
- Price: r.Price,
- ValidStart: r.ValidStart,
- ValidEnd: r.ValidEnd,
- EffectType: r.EffectType,
- RewardMultiplierX1000: r.RewardMultiplierX1000,
- BoostRateX1000: r.BoostRateX1000,
- StackingStrategy: r.StackingStrategy,
- MaxEffectValueX1000: r.MaxEffectValueX1000,
- Remark: r.Remark,
- }
- }
+ res.List = make([]itemCardListItem, len(rows))
+ for i, r := range rows {
+ res.List[i] = itemCardListItem{
+ ID: r.ID,
+ CreatedAt: r.CreatedAt,
+ UpdatedAt: r.UpdatedAt,
+ Name: r.Name,
+ Status: r.Status,
+ CardType: r.CardType,
+ ScopeType: r.ScopeType,
+ ActivityCategoryID: r.ActivityCategoryID,
+ ActivityID: r.ActivityID,
+ IssueID: r.IssueID,
+ Price: r.Price,
+ ValidStart: r.ValidStart,
+ ValidEnd: r.ValidEnd,
+ EffectType: r.EffectType,
+ RewardMultiplierX1000: r.RewardMultiplierX1000,
+ BoostRateX1000: r.BoostRateX1000,
+ StackingStrategy: r.StackingStrategy,
+ MaxEffectValueX1000: r.MaxEffectValueX1000,
+ Remark: r.Remark,
+ }
+ }
ctx.Payload(res)
}
}
diff --git a/internal/api/admin/livestream_admin.go b/internal/api/admin/livestream_admin.go
index ef84eea..bc157d8 100755
--- a/internal/api/admin/livestream_admin.go
+++ b/internal/api/admin/livestream_admin.go
@@ -915,13 +915,13 @@ func (h *handler) ListLivestreamDrawLogs() core.HandlerFunc {
Remark string
}
var invRows []invRow
- _ = h.repo.GetDbR().Table("user_inventory").
- Select("user_inventory.user_id, COALESCE(NULLIF(user_inventory.value_cents, 0), activity_reward_settings.price_snapshot_cents, products.price, 0) as value_cents, user_inventory.remark").
- Joins("LEFT JOIN activity_reward_settings ON activity_reward_settings.id = user_inventory.reward_id").
- Joins("LEFT JOIN products ON products.id = user_inventory.product_id").
- Where("user_inventory.status IN (1,3)").
- Where("COALESCE(user_inventory.remark, '') NOT LIKE ?", "%void%").
- Where("user_inventory.user_id > 0").
+ _ = h.repo.GetDbR().Table("user_inventory").
+ Select("user_inventory.user_id, COALESCE(NULLIF(user_inventory.value_cents, 0), activity_reward_settings.price_snapshot_cents, products.price, 0) as value_cents, user_inventory.remark").
+ Joins("LEFT JOIN activity_reward_settings ON activity_reward_settings.id = user_inventory.reward_id").
+ Joins("LEFT JOIN products ON products.id = user_inventory.product_id").
+ Where("user_inventory.status IN (1,3)").
+ Where("COALESCE(user_inventory.remark, '') NOT LIKE ?", "%void%").
+ Where("user_inventory.user_id > 0").
Scan(&invRows).Error
invByUser := make(map[int64][]invRow)
for _, v := range invRows {
diff --git a/internal/api/admin/livestream_stats.go b/internal/api/admin/livestream_stats.go
index a6abf74..4f4c009 100755
--- a/internal/api/admin/livestream_stats.go
+++ b/internal/api/admin/livestream_stats.go
@@ -5,11 +5,11 @@ import (
"net/http"
"strconv"
"strings"
+ "time"
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/repository/mysql/model"
- "time"
)
type dailyLivestreamStats struct {
diff --git a/internal/api/admin/lottery_admin.go b/internal/api/admin/lottery_admin.go
index ac5f4c0..c11ac34 100755
--- a/internal/api/admin/lottery_admin.go
+++ b/internal/api/admin/lottery_admin.go
@@ -1,13 +1,6 @@
package admin
import (
- "bindbox-game/internal/code"
- "bindbox-game/internal/pkg/core"
- paypkg "bindbox-game/internal/pkg/pay"
- "bindbox-game/internal/pkg/validation"
- "bindbox-game/internal/repository/mysql/model"
- strat "bindbox-game/internal/service/activity/strategy"
- usersvc "bindbox-game/internal/service/user"
"crypto/hmac"
"crypto/sha256"
"encoding/binary"
@@ -15,6 +8,14 @@ import (
"fmt"
"net/http"
"time"
+
+ "bindbox-game/internal/code"
+ "bindbox-game/internal/pkg/core"
+ paypkg "bindbox-game/internal/pkg/pay"
+ "bindbox-game/internal/pkg/validation"
+ "bindbox-game/internal/repository/mysql/model"
+ strat "bindbox-game/internal/service/activity/strategy"
+ usersvc "bindbox-game/internal/service/user"
)
type participantsResponse struct {
diff --git a/internal/api/admin/matching_audit_admin.go b/internal/api/admin/matching_audit_admin.go
index 5deabe3..9a1184a 100755
--- a/internal/api/admin/matching_audit_admin.go
+++ b/internal/api/admin/matching_audit_admin.go
@@ -1,9 +1,10 @@
package admin
import (
+ "net/http"
+
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
- "net/http"
)
// GetMatchingAudit 获取对对碰审计数据
diff --git a/internal/service/channel/channel.go b/internal/service/channel/channel.go
index a271ffb..e2a5b90 100755
--- a/internal/service/channel/channel.go
+++ b/internal/service/channel/channel.go
@@ -8,7 +8,6 @@ import (
"time"
"bindbox-game/internal/pkg/logger"
- "bindbox-game/internal/pkg/util/remark"
"bindbox-game/internal/repository/mysql"
"bindbox-game/internal/repository/mysql/dao"
"bindbox-game/internal/repository/mysql/model"
@@ -129,163 +128,36 @@ var (
ErrSearchKeywordEmpty = errors.New("search_keyword_empty")
)
-type orderRemarkRow struct {
- Remark string
- CreatedAt time.Time
+type orderAmountRow struct {
+ ActualAmount int64
+ CreatedAt time.Time
}
-// calcPaidByPriceDraw 解析订单 remark,按游戏类型分三路计算实付金额:
-// - Case 1 (抽奖/直购): ActivityID > 0 → activities.price_draw × count
-// - Case 2 (对对碰): IssueID > 0 → activity_issues → activities.price_draw × count
-// - Case 3 (一番赏): PkgID > 0 → game_pass_packages.price × count
-//
+// calcGMVByTotalAmount 按订单原价(total_amount)统计渠道GMV,涵盖全部游戏类型(抽奖、对对碰、一番赏)。
+// 使用 total_amount(活动原价)而非 actual_amount,确保优惠券、道具卡、积分抵扣的订单也完整计入,
+// 与成本(商品价值)保持同一口径,使盈亏计算真实反映业务健康度。
// 返回:总金额(分)、按 dateFmt 格式分组的金额。
-func (s *service) calcPaidByPriceDraw(ctx context.Context, rows []orderRemarkRow, dateFmt string) (int64, map[string]int64) {
- if len(rows) == 0 {
- return 0, nil
+func (s *service) calcGMVByTotalAmount(ctx context.Context, channelID int64, dateFmt string, orderFilter string, startDate, endDate *time.Time) (int64, map[string]int64) {
+ type row struct {
+ TotalAmount int64
+ CreatedAt time.Time
}
-
- type parsedActivity struct {
- activityID int64
- count int64
- dateKey string
- }
- type parsedIssue struct {
- issueID int64
- count int64
- dateKey string
- }
- type parsedPkg struct {
- pkgID int64
- count int64
- dateKey string
+ q := s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
+ Joins("JOIN users ON users.id = orders.user_id").
+ Select("orders.total_amount, orders.created_at").
+ Where(orderFilter, channelID)
+ if startDate != nil && endDate != nil {
+ q = q.Where("orders.created_at >= ? AND orders.created_at <= ?", *startDate, *endDate)
}
+ var rows []row
+ q.Scan(&rows)
- var actItems []parsedActivity
- var issueItems []parsedIssue
- var pkgItems []parsedPkg
-
- actIDSet := make(map[int64]struct{})
- issueIDSet := make(map[int64]struct{})
- pkgIDSet := make(map[int64]struct{})
-
- for _, r := range rows {
- rmk := remark.Parse(r.Remark)
- dateKey := r.CreatedAt.Format(dateFmt)
-
- if rmk.ActivityID > 0 {
- // Case 1: 抽奖/直购 — 直接有 activityID
- actItems = append(actItems, parsedActivity{rmk.ActivityID, rmk.Count, dateKey})
- actIDSet[rmk.ActivityID] = struct{}{}
- } else if rmk.IssueID > 0 {
- // Case 2: 对对碰付费路径 — 只有 issueID,需查 activity_issues
- issueItems = append(issueItems, parsedIssue{rmk.IssueID, rmk.Count, dateKey})
- issueIDSet[rmk.IssueID] = struct{}{}
- } else if rmk.PkgID > 0 {
- // Case 3: 一番赏 — 有 pkgID,需查 game_pass_packages
- pkgItems = append(pkgItems, parsedPkg{rmk.PkgID, rmk.Count, dateKey})
- pkgIDSet[rmk.PkgID] = struct{}{}
- }
- }
-
- // ── Case 2: 批量查 activity_issues → 拿到 activityID ──
- issueActivityMap := make(map[int64]int64) // issueID → activityID
- if len(issueIDSet) > 0 {
- issueIDs := make([]int64, 0, len(issueIDSet))
- for id := range issueIDSet {
- issueIDs = append(issueIDs, id)
- }
- type issueRow struct {
- ID int64
- ActivityID int64
- }
- var issueRows []issueRow
- s.readDB.ActivityIssues.WithContext(ctx).UnderlyingDB().
- Table("activity_issues").
- Select("id, activity_id").
- Where("id IN ?", issueIDs).
- Scan(&issueRows)
- for _, ir := range issueRows {
- issueActivityMap[ir.ID] = ir.ActivityID
- actIDSet[ir.ActivityID] = struct{}{} // 合并到 actIDSet 一起查 price_draw
- }
- }
-
- // ── Case 1+2: 批量查 activities.price_draw(含软删除)──
- priceMap := make(map[int64]int64) // activityID → price_draw
- if len(actIDSet) > 0 {
- actIDs := make([]int64, 0, len(actIDSet))
- for id := range actIDSet {
- actIDs = append(actIDs, id)
- }
- var acts []model.Activities
- s.readDB.Activities.WithContext(ctx).UnderlyingDB().
- Unscoped().
- Table("activities").
- Select("id, price_draw").
- Where("id IN ?", actIDs).
- Find(&acts)
- for _, a := range acts {
- priceMap[a.ID] = a.PriceDraw
- }
- }
-
- // ── Case 3: 批量查 game_pass_packages.price ──
- pkgPriceMap := make(map[int64]int64) // pkgID → price
- if len(pkgIDSet) > 0 {
- pkgIDs := make([]int64, 0, len(pkgIDSet))
- for id := range pkgIDSet {
- pkgIDs = append(pkgIDs, id)
- }
- type pkgRow struct {
- ID int64
- Price int64
- }
- var pkgRows []pkgRow
- s.readDB.Activities.WithContext(ctx).UnderlyingDB().
- Unscoped().
- Table("game_pass_packages").
- Select("id, price").
- Where("id IN ?", pkgIDs).
- Scan(&pkgRows)
- for _, pr := range pkgRows {
- pkgPriceMap[pr.ID] = pr.Price
- }
- }
-
- // ── 累加金额 ──
var total int64
byDate := make(map[string]int64)
-
- // Case 1: 抽奖/直购
- for _, item := range actItems {
- if price, ok := priceMap[item.activityID]; ok {
- amt := price * item.count
- total += amt
- byDate[item.dateKey] += amt
- }
+ for _, r := range rows {
+ total += r.TotalAmount
+ byDate[r.CreatedAt.Format(dateFmt)] += r.TotalAmount
}
-
- // Case 2: 对对碰
- for _, item := range issueItems {
- if actID, ok := issueActivityMap[item.issueID]; ok {
- if price, ok := priceMap[actID]; ok {
- amt := price * item.count
- total += amt
- byDate[item.dateKey] += amt
- }
- }
- }
-
- // Case 3: 一番赏
- for _, item := range pkgItems {
- if price, ok := pkgPriceMap[item.pkgID]; ok {
- amt := price * item.count
- total += amt
- byDate[item.dateKey] += amt
- }
- }
-
return total, byDate
}
@@ -304,7 +176,7 @@ func (s *service) calcCostByInventory(ctx context.Context, channelID int64, date
Table("user_inventory").
Select(`
COALESCE(NULLIF(user_inventory.value_cents, 0), activity_reward_settings.price_snapshot_cents, products.price, 0) AS unit_cost,
- GREATEST(COALESCE(system_item_cards.reward_multiplier_x1000, 1000), 1000) AS multiplier,
+ CASE WHEN COALESCE(system_item_cards.reward_multiplier_x1000, 1000) < 1000 THEN 1000 ELSE COALESCE(system_item_cards.reward_multiplier_x1000, 1000) END AS multiplier,
user_inventory.created_at
`).
Joins("JOIN users ON users.id = user_inventory.user_id").
@@ -317,7 +189,8 @@ func (s *service) calcCostByInventory(ctx context.Context, channelID int64, date
Where("user_inventory.status IN ?", []int{1, 3}).
Where("COALESCE(user_inventory.remark, '') NOT LIKE ?", "%void%").
Where("(orders.status = 2 OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)").
- Where("(orders.source_type IN (1,2,3,4) OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)")
+ Where("(orders.source_type IN (2,3,4) OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)").
+ Where("(orders.total_amount > 0 OR user_inventory.order_id = 0 OR user_inventory.order_id IS NULL)")
if startDate != nil && endDate != nil {
q = q.Where("user_inventory.created_at >= ? AND user_inventory.created_at <= ?", *startDate, *endDate)
@@ -418,28 +291,20 @@ func (s *service) List(ctx context.Context, in ListInput) (items []*ChannelWithS
}
}
- type PaidResult struct {
- ChannelID int64
- Remark string
- CreatedAt time.Time
+ type GMVResult struct {
+ ChannelID int64
+ TotalAmount int64
}
- var paidResults []PaidResult
+ var gmvResults []GMVResult
err = s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
Joins("JOIN users ON users.id = orders.user_id").
- Select("users.channel_id, orders.remark, orders.created_at").
+ Select("users.channel_id, orders.total_amount").
Where("users.channel_id IN ?", channelIDs).
- Where("users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)").
- Scan(&paidResults).Error
+ Where("users.deleted_at IS NULL AND orders.status = 2 AND orders.total_amount > 0 AND orders.actual_amount > 0 AND orders.source_type IN (2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)").
+ Scan(&gmvResults).Error
if err == nil {
- grouped := make(map[int64][]orderRemarkRow)
- for _, r := range paidResults {
- grouped[r.ChannelID] = append(grouped[r.ChannelID], orderRemarkRow{
- Remark: r.Remark, CreatedAt: r.CreatedAt,
- })
- }
- for chID, rows := range grouped {
- total, _ := s.calcPaidByPriceDraw(ctx, rows, "2006-01-02")
- paidStats[chID] = total
+ for _, r := range gmvResults {
+ paidStats[r.ChannelID] += r.TotalAmount
}
}
}
@@ -468,7 +333,9 @@ func (s *service) GetStats(ctx context.Context, channelID int64, days int, start
}
out := &StatsOutput{}
- orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+ // source_type: 2=小程序抽奖 3=对对碰 4=一番赏/次卡 5=直播间抽奖抖店(不计入);排除商城直购(1)
+ // actual_amount>0 排除次卡免费使用的订单(避免与购买次卡的订单重复计入GMV)
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.total_amount > 0 AND orders.actual_amount > 0 AND orders.source_type IN (2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
// ========== 1. Overview(全量,不限时间)==========
@@ -484,14 +351,7 @@ func (s *service) GetStats(ctx context.Context, channelID int64, days int, start
Scan(&cr)
out.Overview.TotalOrders = cr.Count
- var allRemarks []orderRemarkRow
- s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
- Joins("JOIN users ON users.id = orders.user_id").
- Select("orders.remark, orders.created_at").
- Where(orderFilter, channelID).
- Scan(&allRemarks)
-
- totalPaid, _ := s.calcPaidByPriceDraw(ctx, allRemarks, "2006-01-02")
+ totalPaid, _ := s.calcGMVByTotalAmount(ctx, channelID, "2006-01-02", orderFilter, nil, nil)
out.Overview.TotalPaidCents = totalPaid
out.Overview.TotalGMV = totalPaid / 100
@@ -553,14 +413,7 @@ func (s *service) GetStats(ctx context.Context, channelID int64, days int, start
}
}
- var rangeRemarks []orderRemarkRow
- s.readDB.Orders.WithContext(ctx).UnderlyingDB().Table("orders").
- Joins("JOIN users ON users.id = orders.user_id").
- Select("orders.remark, orders.created_at").
- Where(orderFilter+" AND orders.created_at >= ? AND orders.created_at <= ?", channelID, startDate, endDate).
- Scan(&rangeRemarks)
-
- _, dailyPaid := s.calcPaidByPriceDraw(ctx, rangeRemarks, "2006-01-02")
+ _, dailyPaid := s.calcGMVByTotalAmount(ctx, channelID, "2006-01-02", orderFilter, &startDate, &endDate)
for dateKey, paid := range dailyPaid {
if item, ok := dateMap[dateKey]; ok {
item.PaidCents = paid
diff --git a/internal/service/channel/channel_stats_test.go b/internal/service/channel/channel_stats_test.go
new file mode 100644
index 0000000..1230d8d
--- /dev/null
+++ b/internal/service/channel/channel_stats_test.go
@@ -0,0 +1,283 @@
+package channel
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "bindbox-game/internal/pkg/logger"
+ "bindbox-game/internal/repository/mysql"
+ "bindbox-game/internal/repository/mysql/dao"
+)
+
+// setupTestService 创建使用 SQLite 内存库的 service 实例及基础表结构。
+func setupTestService(t *testing.T) (*service, mysql.Repo) {
+ t.Helper()
+ repo, err := mysql.NewSQLiteRepoForTest()
+ if err != nil {
+ t.Fatal(err)
+ }
+ ddls := []string{
+ `CREATE TABLE channels (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL,
+ code TEXT NOT NULL,
+ type TEXT NOT NULL DEFAULT 'other',
+ remarks TEXT,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ deleted_at DATETIME
+ )`,
+ `CREATE TABLE users (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ deleted_at DATETIME,
+ nickname TEXT NOT NULL,
+ avatar TEXT,
+ mobile TEXT,
+ openid TEXT,
+ unionid TEXT,
+ invite_code TEXT NOT NULL,
+ inviter_id INTEGER DEFAULT 0,
+ status INTEGER NOT NULL DEFAULT 1,
+ douyin_id TEXT,
+ channel_id INTEGER DEFAULT 0,
+ douyin_user_id TEXT,
+ remark TEXT NOT NULL DEFAULT ''
+ )`,
+ `CREATE TABLE orders (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ user_id INTEGER NOT NULL,
+ status INTEGER NOT NULL,
+ actual_amount INTEGER NOT NULL DEFAULT 0,
+ total_amount INTEGER NOT NULL DEFAULT 0,
+ source_type INTEGER NOT NULL DEFAULT 1,
+ ext_order_id TEXT NOT NULL DEFAULT '',
+ remark TEXT NOT NULL DEFAULT '',
+ item_card_id INTEGER DEFAULT 0,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
+ )`,
+ `CREATE TABLE user_inventory (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ user_id INTEGER NOT NULL,
+ order_id INTEGER DEFAULT 0,
+ reward_id INTEGER DEFAULT 0,
+ product_id INTEGER DEFAULT 0,
+ status INTEGER NOT NULL DEFAULT 1,
+ value_cents INTEGER DEFAULT 0,
+ remark TEXT NOT NULL DEFAULT '',
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
+ )`,
+ `CREATE TABLE activity_reward_settings (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ price_snapshot_cents INTEGER DEFAULT 0
+ )`,
+ `CREATE TABLE products (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ price INTEGER DEFAULT 0
+ )`,
+ `CREATE TABLE user_item_cards (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ card_id INTEGER DEFAULT 0
+ )`,
+ `CREATE TABLE system_item_cards (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ reward_multiplier_x1000 INTEGER DEFAULT 1000
+ )`,
+ }
+ for _, ddl := range ddls {
+ if err := repo.GetDbW().Exec(ddl).Error; err != nil {
+ t.Fatalf("DDL failed: %v\nSQL: %s", err, ddl)
+ }
+ }
+ lg, err := logger.NewCustomLogger(logger.WithOutputInConsole())
+ if err != nil {
+ t.Fatal(err)
+ }
+ q := dao.Use(repo.GetDbR())
+ svc := &service{logger: lg, readDB: q, writeDB: dao.Use(repo.GetDbW())}
+ return svc, repo
+}
+
+// mustExec 执行 SQL,失败则 Fatal。
+func mustExec(t *testing.T, repo mysql.Repo, sql string, args ...interface{}) {
+ t.Helper()
+ if err := repo.GetDbW().Exec(sql, args...).Error; err != nil {
+ t.Fatalf("exec failed: %v\nSQL: %s", err, sql)
+ }
+}
+
+// TestCalcGMVByTotalAmount_ThreeGameTypes 验证三种游戏类型的原价都被正确统计。
+// 使用 total_amount(活动原价)确保优惠券、道具卡免单的订单也完整计入。
+func TestCalcGMVByTotalAmount_ThreeGameTypes(t *testing.T) {
+ svc, repo := setupTestService(t)
+
+ mustExec(t, repo, `INSERT INTO channels (id, name, code, type, remarks) VALUES (1, '测试渠道', 'TEST', 'other', '')`)
+ mustExec(t, repo, `INSERT INTO users (id, nickname, invite_code, status, channel_id) VALUES (1, 'u1', 'I1', 1, 1)`)
+
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.total_amount > 0 AND orders.actual_amount > 0 AND orders.source_type IN (2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ // 抽奖订单 source=2,actual_amount < total_amount(道具卡折扣)
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (1, 2, 800, 1000, 2, '', 'lottery:activity:10|count:1')`)
+ // 对对碰付费 source=3
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (1, 2, 500, 500, 3, '', 'matching_game:issue:50')`)
+ // 一番赏 source=4
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (1, 2, 800, 800, 4, '', 'game_pass_package:幸运|pkg_id:7|count:2')`)
+ // 次卡免费使用:actual_amount=0 但 total_amount=600,不应计入GMV(避免与购买次卡重复计数)
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (1, 2, 0, 600, 2, '', 'lottery:activity:10|count:1|use_game_pass')`)
+ // 过滤条件:status!=2,不应计入
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (1, 1, 9999, 9999, 2, '', 'lottery:activity:10|count:1')`)
+ // 过滤条件:total_amount=0,不应计入
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (1, 2, 0, 0, 2, '', 'lottery:activity:10|count:1')`)
+ // 过滤条件:有 ext_order_id,不应计入
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (1, 2, 9999, 9999, 2, 'EXT-1', 'lottery:activity:10|count:1')`)
+
+ total, byDate := svc.calcGMVByTotalAmount(context.Background(), 1, "2006-01-02", orderFilter, nil, nil)
+
+ // 1000 + 500 + 800 = 2300(次卡免费使用actual=0的600不计入)
+ if total != 2300 {
+ t.Errorf("total = %d, want 2300 (抽奖1000 + 对对碰500 + 一番赏800)", total)
+ }
+ if len(byDate) == 0 {
+ t.Error("byDate should not be empty")
+ }
+}
+
+// TestCalcGMVByTotalAmount_DateFilter 验证时间范围过滤正确。
+func TestCalcGMVByTotalAmount_DateFilter(t *testing.T) {
+ svc, repo := setupTestService(t)
+
+ mustExec(t, repo, `INSERT INTO channels (id, name, code, type, remarks) VALUES (1, '测试渠道', 'TEST', 'other', '')`)
+ mustExec(t, repo, `INSERT INTO users (id, nickname, invite_code, status, channel_id) VALUES (1, 'u1', 'I1', 1, 1)`)
+
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.total_amount > 0 AND orders.actual_amount > 0 AND orders.source_type IN (2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, created_at) VALUES (1, 2, 500, 500, 2, '', '2026-03-01 10:00:00')`)
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, created_at) VALUES (1, 2, 300, 300, 3, '', '2026-03-05 10:00:00')`)
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id, created_at) VALUES (1, 2, 700, 700, 4, '', '2026-03-10 10:00:00')`)
+
+ start, _ := time.Parse("2006-01-02", "2026-03-02")
+ end, _ := time.Parse("2006-01-02", "2026-03-09")
+ end = end.Add(24*time.Hour - time.Second)
+
+ total, byDate := svc.calcGMVByTotalAmount(context.Background(), 1, "2006-01-02", orderFilter, &start, &end)
+
+ // 只有 03-05 的 300 在范围内
+ if total != 300 {
+ t.Errorf("total = %d, want 300 (only 2026-03-05 order)", total)
+ }
+ if byDate["2026-03-05"] != 300 {
+ t.Errorf("byDate[2026-03-05] = %d, want 300", byDate["2026-03-05"])
+ }
+ if byDate["2026-03-01"] != 0 && byDate["2026-03-10"] != 0 {
+ t.Error("dates outside range should not appear")
+ }
+}
+
+// TestCalcGMVByTotalAmount_MultiChannel 验证不同渠道数据互不干扰。
+func TestCalcGMVByTotalAmount_MultiChannel(t *testing.T) {
+ svc, repo := setupTestService(t)
+
+ mustExec(t, repo, `INSERT INTO channels (id, name, code, type, remarks) VALUES (1, '渠道A', 'CA', 'other', ''), (2, '渠道B', 'CB', 'other', '')`)
+ mustExec(t, repo, `INSERT INTO users (id, nickname, invite_code, status, channel_id) VALUES (1, 'u1', 'I1', 1, 1)`)
+ mustExec(t, repo, `INSERT INTO users (id, nickname, invite_code, status, channel_id) VALUES (2, 'u2', 'I2', 1, 2)`)
+
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.total_amount > 0 AND orders.actual_amount > 0 AND orders.source_type IN (2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id) VALUES (1, 2, 1000, 1000, 2, '')`)
+ mustExec(t, repo, `INSERT INTO orders (user_id, status, actual_amount, total_amount, source_type, ext_order_id) VALUES (2, 2, 2000, 2000, 3, '')`)
+
+ total1, _ := svc.calcGMVByTotalAmount(context.Background(), 1, "2006-01-02", orderFilter, nil, nil)
+ total2, _ := svc.calcGMVByTotalAmount(context.Background(), 2, "2006-01-02", orderFilter, nil, nil)
+
+ if total1 != 1000 {
+ t.Errorf("channel1 total = %d, want 1000", total1)
+ }
+ if total2 != 2000 {
+ t.Errorf("channel2 total = %d, want 2000", total2)
+ }
+}
+
+// TestCalcCostByInventory_Basic 验证成本从 value_cents 读取。
+func TestCalcCostByInventory_Basic(t *testing.T) {
+ svc, repo := setupTestService(t)
+
+ mustExec(t, repo, `INSERT INTO channels (id, name, code, type, remarks) VALUES (1, '测试渠道', 'TEST', 'other', '')`)
+ mustExec(t, repo, `INSERT INTO users (id, nickname, invite_code, status, channel_id) VALUES (1, 'u1', 'I1', 1, 1)`)
+
+ // status=1(待发货) 和 status=3(已发货) 都计入成本
+ mustExec(t, repo, `INSERT INTO user_inventory (user_id, order_id, status, value_cents, remark) VALUES (1, 0, 1, 500, '')`)
+ mustExec(t, repo, `INSERT INTO user_inventory (user_id, order_id, status, value_cents, remark) VALUES (1, 0, 3, 300, '')`)
+ // status=2 不计入
+ mustExec(t, repo, `INSERT INTO user_inventory (user_id, order_id, status, value_cents, remark) VALUES (1, 0, 2, 999, '')`)
+ // remark含void 不计入
+ mustExec(t, repo, `INSERT INTO user_inventory (user_id, order_id, status, value_cents, remark) VALUES (1, 0, 1, 888, 'void-item')`)
+
+ total, byDate := svc.calcCostByInventory(context.Background(), 1, "2006-01-02", nil, nil)
+
+ // 500 + 300 = 800
+ if total != 800 {
+ t.Errorf("cost total = %d, want 800", total)
+ }
+ if len(byDate) == 0 {
+ t.Error("byDate should not be empty")
+ }
+}
+
+// TestProfitLoss_AllGameTypes 端到端验证盈亏 = GMV(原价) - 成本,覆盖三种游戏类型及道具卡免单。
+// 核心场景:道具卡免单订单 actual_amount=0 但 total_amount=活动原价,成本真实存在,
+// 使用 total_amount 口径确保盈亏计算准确。
+func TestProfitLoss_AllGameTypes(t *testing.T) {
+ svc, repo := setupTestService(t)
+
+ mustExec(t, repo, `INSERT INTO channels (id, name, code, type, remarks) VALUES (1, '测试渠道', 'TEST', 'other', '')`)
+ mustExec(t, repo, `INSERT INTO users (id, nickname, invite_code, status, channel_id) VALUES (1, 'u1', 'I1', 1, 1)`)
+
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.total_amount > 0 AND orders.actual_amount > 0 AND orders.source_type IN (2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ // 收入:3种游戏(total_amount = 活动原价)
+ mustExec(t, repo, `INSERT INTO orders (id, user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (1, 1, 2, 4600, 4600, 2, '', 'lottery:activity:10|count:1')`) // 抽奖 46元
+ mustExec(t, repo, `INSERT INTO orders (id, user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (2, 1, 2, 1086, 1086, 3, '', 'matching_game:issue:50')`) // 对对碰 10.86元
+ mustExec(t, repo, `INSERT INTO orders (id, user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (3, 1, 2, 3320, 3320, 4, '', 'game_pass_package:x|pkg_id:7|count:2')`) // 一番赏 33.20元
+ // 次卡免费使用:actual_amount=0,total_amount=2000,不计入GMV(避免重复计数),但成本仍计入
+ mustExec(t, repo, `INSERT INTO orders (id, user_id, status, actual_amount, total_amount, source_type, ext_order_id, remark) VALUES (4, 1, 2, 0, 2000, 2, '', 'lottery:activity:10|count:1|use_game_pass')`)
+
+ // 成本:库存资产
+ mustExec(t, repo, `INSERT INTO user_inventory (user_id, order_id, status, value_cents, remark) VALUES (1, 0, 1, 8000, '')`) // 成本 80元
+
+ totalGMV, _ := svc.calcGMVByTotalAmount(context.Background(), 1, "2006-01-02", orderFilter, nil, nil)
+ totalCost, _ := svc.calcCostByInventory(context.Background(), 1, "2006-01-02", nil, nil)
+ profit := totalGMV - totalCost
+
+ // GMV = 4600 + 1086 + 3320 = 9006(次卡免费使用的2000不计入)
+ if totalGMV != 9006 {
+ t.Errorf("totalGMV = %d, want 9006 (抽奖4600 + 对对碰1086 + 一番赏3320)", totalGMV)
+ }
+ // 成本 = 8000
+ if totalCost != 8000 {
+ t.Errorf("totalCost = %d, want 8000", totalCost)
+ }
+ // 盈亏 = 9006 - 8000 = 1006
+ if profit != 1006 {
+ t.Errorf("profit = %d, want 1006", profit)
+ }
+}
+
+// TestCalcGMVByTotalAmount_Empty 验证无订单时返回零值。
+func TestCalcGMVByTotalAmount_Empty(t *testing.T) {
+ svc, repo := setupTestService(t)
+
+ mustExec(t, repo, `INSERT INTO channels (id, name, code, type, remarks) VALUES (1, '空渠道', 'EMPTY', 'other', '')`)
+
+ orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.total_amount > 0 AND orders.actual_amount > 0 AND orders.source_type IN (2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
+
+ total, byDate := svc.calcGMVByTotalAmount(context.Background(), 1, "2006-01-02", orderFilter, nil, nil)
+
+ if total != 0 {
+ t.Errorf("empty channel total = %d, want 0", total)
+ }
+ if len(byDate) != 0 {
+ t.Errorf("byDate should be empty, got %v", byDate)
+ }
+}
diff --git a/web/.DS_Store b/web/.DS_Store
index 9915eea..164f4c7 100755
Binary files a/web/.DS_Store and b/web/.DS_Store differ