1. Bussiness | Logic
Traffic Tool
  • Traffic Tool Docs
    • Tổng Quan
    • project
      • admin
        • Hướng dẫn sử dung
          • Đăng Nhập & Xác Thực Hai Bước
          • Thống Kê Hệ Thống
          • Thống Kê Hàng Ngày
          • Tìm Kiếm Tự Động
          • Trung Tâm Báo Cáo
          • Quản Lý Tài Khoản
          • Quản Lý Server
          • Quản Lý Proxy
          • Quản Lý Gói Proxy
          • Quản Lý Nhà Cung Cấp Proxy
          • Quản Lý Backup Proxy
          • Quản Lý Tài Khoản Google
      • api + tool
        • Hướng dẫn sử dụng
          • User Guide
          • Setup Guide
        • Bussiness | Logic
          • 1. Thống kê hàng ngày (Daily Statistics)
          • 2. Thống kê hệ thống (System Statistics)
          • 3. Tìm kiếm tự động (Automated Discovery)
          • 4. Trung tâm Báo cáo (Report Center)
          • 5. Quản lý tài khoản (Account Management)
          • 6. Quản lý Hệ thống (System Management)
          • 7. Quản lý tài khoản Google (Google Account Management)
        • Architecture
          • Database Schema
          • System Architecture
          • Code Structure
          • Logs and Monitoring
          • Environment & Configuration
        • Deployment
          • Local
          • Staging
          • Product
  • Traffic Backend API
    • 🔑 Identity & Session
      • Đăng nhập hệ thống (Login)
      • Đăng ký tài khoản mới (Public)
      • Lấy danh sách người dùng (Phân trang)
      • Admin tạo người dùng mới
      • Lấy thông tin cá nhân hiện tại
      • Khởi tạo bảo mật 2FA
      • Xác thực mã OTP
      • Chi tiết người dùng theo ID
      • Cập nhật thông tin người dùng
      • Xóa tài khoản người dùng
      • Đổi mật khẩu
      • Kiểm tra Cấu hình Thông báo Telegram Toàn hệ thống
      • Bật/Tắt Thông báo Telegram Toàn cục
    • 📁 Campaign Management
      • Danh sách Chiến dịch Toàn cầu
      • Khởi tạo Chiến dịch Mới
      • Chi tiết Chiến dịch
      • Cập nhật Chiến dịch
      • Xóa Chiến dịch
      • Tắt/Mở Chiến dịch (Hàng loạt)
      • Dữ liệu Hình mẫu SEO (Negative SEO)
    • ⚙️ Project Mechanics
      • Danh sách Dự án (Projects List)
      • Khởi tạo Kịch bản Mô phỏng
      • Lấy chi tiết cấu hình Dự án
      • Cập nhật Kịch bản chạy
      • Xóa Dự án
      • Chỉnh sửa Hàng loạt (Bulk)
      • Bật/Tắt Dự án
    • 👤 Profile Management
      • Danh sách Vân tay số (Profiles Data)
      • Tạo Hồ sơ Đơn lẻ (Tạo Vân tay mới)
      • Nhập kho Tài khoản Email (Bulk Import)
      • Chi tiết Session/Cookies
      • Chỉnh sửa Hồ sơ/Ghi chú
      • Xóa Vân tay số và Dữ liệu Local
      • Mở khóa Captcha/Trạng thái Blocked
      • Tra cứu Kho Profile Khả dụng
      • Báo cáo Sức khỏe Kho Tài Khoản
    • 🦾 Worker Interface
      • Đăng ký Khởi tạo Node (Handshake)
      • Nhịp Tim Khảo Sát Tình Trạng (Heartbeat)
      • Nhận Cấu hình Bypass & Hệ thống
      • Kéo (PULL) Nhiệm vụ Traffic SEO
      • Báo cáo Sự cố Node (Crash Report)
    • 📊 Report: Execution
      • Kéo Công việc Báo cáo (Worker Pull)
      • Quản lý Giám sát Nhiệm vụ (Task Dashboard)
      • Bắn Lại Báo Cáo Thất Bại (Manual Retry)
    • 📊 Report: Discovery
      • Danh sách Tên miền Chờ Xử Lý (Discovery Pool)
      • Nhập Mục Tiêu Thủ Công (Manual Insert)
      • Kích hoạt Heuristic Scanner (Cào tự động)
      • Chi tiết Bằng Chứng (Evidence Data)
      • Dán nhãn Vi Phạm / Cập nhật Screenshot
      • Loại Bỏ Mục Tiêu
      • Duyệt Yêu Cầu (Approve to Execution)
    • 📊 Report: Platforms Configuration
      • Truy vấn Danh sách Nền tảng Đối tác (Vendor)
      • Tạo Nền tảng Vendor Báo cáo Mới
      • Bật/Tắt Trang báo cáo theo Loại
      • Cập nhật Metadata Trang
      • Xóa Trang Báo Cáo
      • Lấy Cài đặt LLM cho Vendor cụ thể
      • Cập nhật Cài đặt Tạo mẫu LLM
      • Lấy Cấu hình Schema Biểu mẫu cho Vendor
      • Cập nhật Yêu cầu Trường Biểu mẫu
    • 📊 Report: Email Automation
      • Danh sách SMTP/Mailer Server
      • Thêm kết nối SMTP Mới
      • Nhật ký Nhiệm vụ Gửi Mail (Email Log)
      • Phân tích Tỉ lệ Chuyển đổi (Email Delivery Analytics)
    • 🌐 Global Proxies
      • Danh sách Kho Proxy Phân trang (Proxy Pool)
      • Thêm mới Tuyến IP (Bulk Import)
      • Cập nhật Thông tin máy chủ Proxy
      • Xóa Proxy (Thu hồi tài nguyên)
      • Kích hoạt Xoay vòng (Rotate IP) Cưỡng bức
    • 📈 System Intelligence
      • Báo cáo Luồng Bảo mật Hợp nhất (Colossal Report)
      • Bản Đồ Lưu Lượng GeoIP (Heatmap)
    • 🪝 Webhook Integrations
      • Callback Hoàn tất Gói Lưu lượng SEO (Traffic Node)
      • Callback Thông báo Hoàn tất Bắn Report AI
    • Schemas
      • AppError
      • LoginRequest
      • UserResponseDto
      • UserModel
      • CreateUserRequest
      • UpdateUserRequest
      • PagingInfo
      • ProfileModel
      • CreateProfileRequest
      • BulkImportProfileReq
      • UpdateProfileRequest
      • CampaignModel
      • CampaignConfigs
      • CreateCampaignRequest
      • UpdateCampaignRequest
      • BulkUpdateCampaignStatusReq
      • NegativeSeoData
      • CreateProjectRequest
      • UpdateProjectRequest
      • ProjectModel
      • BulkUpdateProjectRequest
      • ProjectAttribute
      • WorkerHandshakeRequest
      • WorkerHandshakeResponse
      • WorkerHeartbeatPayload
      • WorkerGlobalSettings
      • TaskPullRequest
      • WorkerFatalLog
      • TaskModel
      • TaskTrafficType
      • TaskUpdateDto
      • ReportTaskModel
      • ReportTaskResult
      • PCReportResponse
      • SummaryStats
      • DailyStats
      • BrandStats
      • ProfileStats
      • ReportTaskItem
      • ReportSiteItem
      • CreateReportSiteRequest
      • GPTConfig
      • ResponseConfig
      • FieldConfig
      • ReportDomainsResponse
      • ReportDomainItem
      • AddReportDomainRequest
      • UpdateReportDomainRequest
      • BulkUpdateDashboardRequest
      • ProxyModel
      • CreateProxyRequest
      • UpdateProxyRequest
      • SMTPServerConfig
      • EmailTaskLog
      • GeoLocation
  • Traffic Tools V2 API
    • Tasks
      • Lọc và Truy vấn Nhật ký Phiên Duyệt lẻ
      • Get all tasks
      • Nạp Kết Quả Chạy của Puppeteer (Update Callback)
      • Xóa toàn bộ Tasks lẻ
      • Get all tasks
      • Xóa một Task (ID)
    • Group task
      • Đẩy nhóm công việc Traffic theo lô (Batch Pipeline Task Creation)
      • Lấy sơ đồ trạng thái hàng đợi Group Tasks
      • Endpoint /api/task-traffics/
      • Clear/Flush Hàng đợi Group Task (Kill Queue)
      • Endpoint /api/task-traffics/
      • Xóa 1 nhóm nhiệm vụ (Theo ObjectID Mongoose)
      • Parse chuỗi Proxy
    • Test
      • Kiểm tra Proxy hoạt động ngầm
      • Endpoint /api/test
      • Kho Fingerprint Thử Nghiệm
      • Endpoint /api/test/account-stats
      • Endpoint /api/test/session-recommendation
      • Endpoint /api/test/check-browser
      • Endpoint /api/test/clear-browser-sessions
    • Proxies
      • Lấy kho Proxy server
      • Khai báo Pool Tuyến Proxy mới
      • Get all proxies
      • Get all proxies
      • Xóa toàn bộ Proxy
      • Get all proxies
      • Xóa Proxy theo ID
      • Reset lại số đếm tiến trình (Cron Proxy Thread)
    • Report Platforms
      • Submit report to multiple platforms
      • Submit report to specific platform
      • Get available platforms
      • Get platform statistics
      • Health check
    • Reports
      • Create a new report
      • Create a new report
      • Get report by ID
      • Get report by ID
      • Get report statistics
      • Get report groups
      • Get report groups
      • Get report group
      • Add report to group
      • Bulk add reports to group
      • Get report group statistics
      • Get analytics data
      • Get platform success rates
      • Get reports by platform
      • Get reports by group
      • Create test reports in bulk
    • Test Report
      • Test Microsoft report submission
      • Test AdGuard report submission
      • Test Google Ads report submission
      • Test Spamhaus report submission
      • Test ESET report submission
      • Test multi-platform report submission
      • Get available platforms
    • ESET Test
      • Simple test
      • Minimal POST test
      • Generate ESET report content
      • Get sample test data
      • Test form filling
      • Test full form submission
    • Spamhaus Test
      • Simple test
      • Minimal POST test
      • Generate Spamhaus report content
      • Get sample test data
      • Test Spamhaus form filling
      • Test full Spamhaus form submission
    • Report Scheduler
      • Get report scheduler statistics
      • Process ad detection result
      • Submit a scheduled report
      • Start report scheduler
      • Stop report scheduler
      • Get scheduler status
      • Process scheduled reports
      • Test browser session (non-headless)
      • Test report submission (non-headless)
    • Comprehensive Analytics
      • Get comprehensive dashboard analytics
      • Get overview statistics
      • Get brand-wise statistics
      • Get daily statistics
      • Get platform success rates
      • Get account performance
      • Get summary report
    • Search
      • Ra lệnh Máy Lọc Dữ Liệu TOP SEO Hàng Loại (Scraper Engine)
      • Đếm tổng số dòng tìm kiếm (Length)
    • Report Tasks
      • Tạo chiến dịch Report (Auto Spawn 14 tasks)
      • Tạo chiến dịch Report Form hàng loạt (Bulk Abuse Report)
      • Create Direct Report (Từ API hệ thống thay vì Frontend)
      • Tạo Nhiệm Vụ Sinh Email Khiếu nại (Automated Bulk Mail Spam)
      • Worker Pull - Lấy task Báo cáo đang Pending
      • Worker Trả kết quả (Report Status)
      • Danh mục Platfoms & Providers
      • Dashboard Statistic Báo Cáo
      • Force Run Cronjob
    • Monitor
      • Xuất dữ liệu đo đếm Hardware (Telemetry OS Watchdog)
    • Schemas
      • CreateTask
      • UpdateTask
      • CreateTaskGroupRequest
      • CreateProxy
      • CreateSearch
      • ReportTaskCreation
      • CreateEmail
      • CreateMultipleSearchRequest
      • CreateMultipleReportRequest
      • UpdateReportStatusRequest
      • TestProxyRequest
  1. Bussiness | Logic

4. Trung tâm Báo cáo (Report Center)

Trung Tâm Báo Cáo — Technical Documentation#

Module: report-dashboard
Frontend: admin/src/views/report-dashboard/
Backend: api/internal/report/
Database: MongoDB (report_sites, report_domains, report_tasks collections)
Route prefix API: /api/reports/

I. Tổng quan module#

Trung Tâm Báo Cáo (Report Center) là hệ thống phụ trách gửi báo cáo tự động về các domain vi phạm (phishing, malware, ads vi phạm) đến các nền tảng bảo mật bên ngoài như Google Safe Browsing, Spamhaus, Kaspersky... thông qua hai cơ chế:
1.
BROWSER_BASED — Worker mở trình duyệt, điều hướng đến URL báo cáo, điền form tự động.
2.
EMAIL_BASED — Backend gửi email đến địa chỉ nhận báo cáo của nhà cung cấp bảo mật.
Module bao gồm 4 tab chính:
TabTênComponent
statisticsThống kêReportStatisticsTab.vue
sitesTrang Báo CáoSiteReportsTab.vue
domainsQuản lý miềnReportDomainPool.vue
pc-reportBáo Cáo PCPCReportDashboard.vue
Auto-refresh: IndexView.vue thiết lập setInterval mỗi 120 giây để tự động cập nhật tab Thống kê khi đang active.

II. Kiến trúc Frontend#

Cây component tổng thể#

IndexView.vue
├── ReportDashboardHeader.vue       ← DateRange picker + title
├── NTabs (4 tab)
│   ├── ReportStatisticsTab.vue     ← Tab Thống kê
│   ├── SiteReportsTab.vue          ← Tab Trang Báo Cáo
│   ├── ReportDomainPool.vue        ← Tab Quản lý miền
│   └── PCReportDashboard.vue       ← Tab Báo Cáo PC
├── TaskDetailModal.vue             ← Modal chi tiết task (global)
└── DomainDetailModal.vue           ← Modal chi tiết domain (global)

Composables chính#

useReportDashboardData (composables/useReportDashboardData.ts):
Quản lý state: reportTasks, chartData, detailedStats, keywordStatistics.
fetchAllData() — Gọi song song Promise.all([reportStore.refreshAll, fetchReportTasks, fetchChartData, fetchDetailedStats]).
Dùng module-level flag (isFetchingReportTasks, v.v.) để ngăn concurrent duplicate fetch.
useReportDashboardOperations (composables/useReportDashboardOperations.ts):
Xử lý onChangePage, onChangePageSize, onExport.
disableDate — Hàm kiểm tra ngày không hợp lệ cho DatePicker.

DateRange state#

IndexView.vue khởi tạo hai ref riêng biệt:
Khi user thay đổi dateRange qua header → chartDateRange được đồng bộ → fetchAllData() được gọi lại.

III. Tab Thống Kê#

Các API được gọi#

EndpointMục đích
GET /api/reports/stats?start_date=&end_date=4 số liệu thẻ thống kê đầu trang
GET /api/reports/statistics/daily?start_date=&end_date=Dữ liệu biểu đồ theo tuần
GET /api/reports/tasks?page=1&page_size=10000&...Chi tiết tasks để tính detailedStats
GET /api/reports/tasks?page=N&page_size=M&...Danh sách tasks phân trang

4 thẻ thống kê đầu trang#

Lấy từ GET /api/reports/stats:
ThẻFieldMô tả
TỔNG BÁO CÁOtotal_reportsTổng số report task trong khoảng ngày
TỶ LỆ THÀNH CÔNGsuccess_ratesuccess_count / total * 100
TỶ LỆ THẤT BẠIfailure_ratefailure_count / total * 100
XỬ LÝ HÔM NAYprocessed_todaySố task được xử lý ngày hôm nay
Backend handler GetReportStats:
Nếu không có start_date/end_date → mặc định lấy hôm nay (00:00:00 đến 23:59:59 UTC).
End date được đặt về 23:59:59.999999999 UTC để bao gồm toàn bộ cuối ngày.

Biểu đồ thống kê theo tuần#

Endpoint: GET /api/reports/statistics/daily?start_date=&end_date=
Response chứa data.keywords — object có key là tên từ khóa, mỗi keyword có:
{
  "total_processed": 20,
  "success_count": 10,
  "failure_count": 5,
  "dates": {
    "2026-03-17": { "success_count": 2, "failure_count": 1, "total_processed": 3 },
    ...
  },
  "hours": { "0": {...}, "1": {...}, ... }
}
Logic xây dựng biểu đồ (trong fetchChartData):
1.
Tạo mảng dates từ startDate đến endDate (mỗi ngày một điểm).
2.
Với mỗi ngày, cộng dồn success, failed, pending từ tất cả keyword.
3.
pending = total_processed - success_count - failure_count.
4.
Kết quả: 3 series — Thành công, Thất bại, Đang chờ.

Danh sách thống kê#

fetchDetailedStats gọi GET /api/reports/tasks?page=1&page_size=10000 để lấy toàn bộ tasks rồi group phía client theo key domain|platform|keyword:
Task status mapping:
COMPLETED → success++
FAILED → failed++
PENDING / IN_PROGRESS / PROCESSING → pending++

IV. Tab Trang Báo Cáo — SiteReportsTab#

Tab này quản lý danh sách các nền tảng báo cáo (Report Sites) mà hệ thống sẽ gửi báo cáo đến.

Cấu trúc#

SiteReportsTab.vue
├── SiteReportsHeader.vue      ← Toolbar (refresh, create, bulk actions)
├── SiteReportsStats.vue       ← 4 số liệu tổng quan
├── SiteReportsFilters.vue     ← Tìm kiếm + filter category/status
├── NTabs (browser / email)    ← Lọc theo loại site
├── SiteReportCard × N         ← Card cho từng site
│
├── SitePromptEditor.vue       ← Modal sửa AI Prompt
├── BulkPromptUpdateModal.vue  ← Modal cập nhật prompt hàng loạt
├── CreateSiteModal.vue        ← Modal tạo site mới
└── EditSiteModal.vue          ← Modal sửa site

Model ReportSite (MongoDB collection: report_sites)#

FieldKiểuMô tả
_idObjectID-
namestringKey định danh, normalized (lowercase, underscores), VD: google_safe_browsing
display_namestringTên hiển thị, VD: Google Safe Browsing
descriptionstringMô tả ngắn
iconstringMDI icon name, VD: mdi:google
urlstringURL form báo cáo (BROWSER_BASED) hoặc địa chỉ email (EMAIL_BASED)
categorystringNhóm: Security, Browser, Social Media, Email, Advertising...
typestringBROWSER_BASED hoặc EMAIL_BASED
enabledboolBật/tắt site này
statusstringactive hoặc inactive
success_countintTổng số lần báo cáo thành công
failure_countintTổng số lần thất bại
success_ratefloat64Tỷ lệ thành công (%)
promptstringAI prompt cho GPT xử lý form
gpt_configGPTConfigCấu hình OpenAI model
response_configResponseConfigĐịnh nghĩa các field cần điền vào form

GPTConfig struct#

ResponseConfig struct#

Worker dùng GPTConfig + prompt + ResponseConfig để tự động điền form báo cáo trên trình duyệt. GPT trả về JSON theo schema định nghĩa, worker map vào các field trên form.

Danh sách Site mặc định (hardcoded trong report_sites_defaults.go)#

BROWSER_BASED (14 sites):
NameDisplayNameURLCategory
SPAMHAUSSpamhaussubmit.spamhaus.org/submit/Security
GOOGLE_SAFE_BROWSINGGoogle Safe Browsingsafebrowsing.google.com/...Security
ADGUARDAdGuardreports.adguard.com/...Ad Blocker
GOOGLE_ADSGoogle Adssupport.google.com/...Advertising
TIKTOKTikToktiktok.com/legal/reportSocial Media
GOOGLE_PLAYGoogle Playsupport.google.com/...App Store
US_CERTUS-CERTus-cert.gov/reportSecurity
ESETESETeset.com/us/support/...Security
MICROSOFT_SMARTSCREENMicrosoft SmartScreenmicrosoft.com/...Security
TREND_MICROTrend Microtrendmicro.com/...Security
X_TWITTERX (Twitter)help.twitter.com/forms/...Social Media
MICROSOFTMicrosoftmicrosoft.com/...Technology
NETCRAFTNetcraftreport.netcraft.com/Security
MOZILLA_FIREFOXMozilla Firefoxmozilla.org/...Browser
EMAIL_BASED (10 sites):
NameDisplayNameEmail Address
KASPERSKY_EMAILKasperskynewvirus@kaspersky.com
ESET_EMAILESETsamples@eset.com
AVAST_EMAILAvastvirus@avast.com
BITDEFENDER_EMAILBitdefendervirus-submission@bitdefender.com
MCAFEE_EMAILMcAfeevirus_research@mcafee.com
SOPHOS_EMAILSophossamples@sophos.com
OPENPHISH_EMAILOpenPhishsubmit@openphish.com
MICROSOFT_EMAILMicrosoftabuse@microsoft.com
GOOGLE_EMAILGooglespam@google.com
PAYPAL_EMAILPayPalspoof@paypal.com
Cơ chế default merge:
Khi GetReportSites load từ MongoDB, nó merge với getDefaultReportSites().
Nếu site đã có trong DB nhưng thiếu display_name / description / icon → lấy giá trị từ default.
Site trong DB nhưng không có trong default → vẫn hiển thị bình thường.

Site name normalization#

Khi tạo site mới, name được normalize bằng normalizeSiteName():
Ví dụ: "Google Safe Browsing!" → google_safe_browsing.

Các hành động Bulk trong SiteReportsTab#

ButtonHandlerAPI
Bật tất cảenableAllSitesPOST /reports/sites/toggle-all {enabled: true}
Tắt tất cảdisableAllSitesPOST /reports/sites/toggle-all {enabled: false}
Bật BrowserhandleEnableBrowserPOST /reports/sites/toggle-by-type {type:"BROWSER_BASED", enabled:true}
Tắt BrowserhandleDisableBrowserPOST /reports/sites/toggle-by-type {type:"BROWSER_BASED", enabled:false}
Bật EmailhandleEnableEmailPOST /reports/sites/toggle-by-type {type:"EMAIL_BASED", enabled:true}
Tắt EmailhandleDisableEmailPOST /reports/sites/toggle-by-type {type:"EMAIL_BASED", enabled:false}
Cập nhật prompt hàng loạtshowBulkPromptModalPOST /reports/sites/bulk-update-prompts

V. Tab Quản Lý Miền — ReportDomainPool#

Tab này quản lý danh sách các domain cần được báo cáo (report_domains).

Model ReportDomain (MongoDB: report_domains)#

FieldKiểuMô tả
_idObjectID-
domainstringURL đầy đủ, bắt đầu bằng http:// hoặc https://
keywordstringTừ khóa liên quan (bắt buộc nếu type = google_ads)
typestringgoogle_ads hoặc normal
statusstringpending / processing / ready / completed
image_urls[]stringURLs screenshot ảnh (do worker upload)
video_urls[]stringURLs screenshot video
third_service_task_id*stringTask ID từ service bên thứ 3
history_domain_id*int64ID từ bảng lịch sử (MySQL)
task_group_id*stringID nhóm task
profile_id*stringProfile được gán
proxy_id*stringProxy được gán
flow*stringLoại flow xử lý
engine*stringEngine sử dụng
report_pages[]stringDanh sách site được chọn để báo cáo
created_attime-
updated_attime-

Validation khi tạo domain mới#

Logic tính toán domain status#

Backend tính status của domain dựa trên trạng thái tất cả report_tasks liên kết:
Nếu có task IN_PROGRESS/PROCESSING → domain.status = "processing"
Nếu có task PENDING và domain đang "ready" → domain.status = "ready"
Nếu có task PENDING → domain.status = "pending"
Nếu tất cả task đã xong (COMPLETED/FAILED) → domain.status = "completed"
Không có task nào → giữ nguyên status từ DB
Task-domain liên kết qua hai cách (OR logic):
1.
report_tasks.report_domain_id == domain._id
2.
report_tasks.domain == domain.domain AND report_tasks.keyword == domain.keyword

Filter trong GetReportDomains#

Sort: created_at DESC. Timeout: 30 seconds.

Xóa domain (soft delete)#

Xóa domain KHÔNG xóa record khỏi MongoDB mà set status = "deleted":
Khi xóa, backend tự động cancel tất cả report_tasks liên quan qua CancelTasksByDomainID.

3 Modal trong ReportDomainPool#

AddDomainModal: Form tạo domain mới với domain, keyword, type.
EditDomainModal: Sửa thông tin domain đã có, gọi POST /reports/bulk-update với ids và fields.
ViewDomainModal: Xem chi tiết domain, gọi GET /reports/domains/:id. Hiển thị:
Thông tin domain + metadata.
Danh sách report_tasks liên kết (với platform_display_name được lookup từ report_sites).
Profile email được tra cứu từ collection profiles theo assigned_profile_id.
Server name/IP được tra cứu từ MySQL servers table theo server_id.

VI. Tab Báo Cáo PC — PCReportDashboard#

Tab này hiển thị báo cáo tổng hợp về quảng cáo vi phạm phát hiện, accounts và keywords.

Cấu trúc#

PCReportDashboard.vue
├── PCReportHeader.vue          ← Title + nút Export CSV
├── SummaryStatisticsCard.vue   ← Bảng tổng hợp Overall + Today + Monthly
├── DailyStatsCard.vue          ← Thống kê hôm nay
├── BrandStatisticsTable.vue    ← Bảng theo từng Brand
└── DailyStatisticsTable.vue    ← Bảng 10 ngày gần nhất

API#

GET /api/reports/pc-report?start_date=&end_date=
Nếu không có ngày → lấy dữ liệu mặc định.

Model PCReportData (Go struct)#

OverallStats bao gồm:
total_ads_found — Tổng quảng cáo đã phát hiện
total_ad_reports — Tổng báo cáo đã gửi
total_ads_rip — Tổng quảng cáo đã bị chết
ad_accounts_count — Tổng số ad account
remaining_accounts — Số account còn sống
dead_accounts — Số account đã chết
keywords_count — Tổng keywords
active_keywords — Keywords đang active
report_success_rate — Tỷ lệ report thành công (%)
completed_reports — Số report đã hoàn thành
failed_reports — Số report thất bại
BrandStats: Thống kê theo brand gồm: ads_detected, reports_count, new_dead_ads, remaining_ads, dead_accounts_percent.

Export CSV#

PCReportHeader có nút export → gọi usePCReportExport.exportPCReport(start, end):
GET /api/reports/pc-report/csv?start_date=&end_date=&brand=&format=csv
Response: file CSV với header Content-Disposition: attachment; filename=pc_report_{date}.csv.
Có hai format:
format=csv → GeneratePCReportCSV() — Full report với tất cả sections.
format=simple → GenerateSimpleCSV() — Chỉ số liệu cốt lõi.

VII. Luồng xử lý Report Task end-to-end#

[Admin] Tạo domain tại tab Quản lý miền
        ↓
[Cron Job / Worker] Lấy task từ MongoDB
  GET /webhook/report/tasks?server_ip=...&limit=5
        ↓
[API] RequestReportTask():
  - GetAndUpdatePendingTasks (MongoDB: report_tasks, status=PENDING)
  - Set task status = IN_PROGRESS
  - Trả về task với webhookURL, proxyURL, profileURL
        ↓
[Worker/tools_v2] Nhận task
  - Gọi proxyURL để lấy proxy sạch
  - Gọi profileURL để lấy browser profile
  - Nếu BROWSER_BASED:
    → Mở trình duyệt với proxy + profile
    → Dùng GPT (prompt + response_config) để phân tích form báo cáo
    → Điền form, submit
    → Screenshot kết quả
  - Nếu EMAIL_BASED:
    → Gửi email đến địa chỉ trong site.url
    → Đính kèm thông tin domain vi phạm
        ↓
[Worker] Gửi callback kết quả về API
  POST /webhook/report/callback/report
  Body: { task_id, result: { success, message, screenshot_url, ... } }
        ↓
[API] Cập nhật report_task:
  - status = COMPLETED hoặc FAILED
  - completed_at, execution_time, result
  - Nếu thành công: cập nhật report_site.success_count++
  - Nếu thất bại: report_site.failure_count++
        ↓
[Frontend] Hiển thị kết quả trong tab Thống kê và Quản lý miền

VIII. API Reference đầy đủ#

Report Tasks#

MethodEndpointMô tả
GET/reports/tasksDanh sách tasks phân trang. Params: page, page_size, domain, keyword, platform, status, start_date, end_date
GET/reports/tasks/monitoringMonitoring tasks đang active
GET/reports/tasks/activeDanh sách tasks đang xử lý
GET/reports/tasks/:idChi tiết một task
GET/reports/stats4 số liệu thống kê tổng quan
GET/reports/chart-dataDữ liệu biểu đồ, param type=tasks

Report Sites#

MethodEndpointMô tả
GET/reports/sitesDanh sách tất cả sites
POST/reports/sitesTạo site mới. Body: {name, display_name, type, url, enabled, prompt, gpt_config, response_config}
PUT/reports/sites/:site_nameCập nhật site
DELETE/reports/sites/:site_nameXóa site
POST/reports/sites/toggleBật/tắt một site. Body: {site_name, enabled}
POST/reports/sites/toggle-allBật/tắt tất cả. Body: {enabled}
POST/reports/sites/toggle-by-typeBật/tắt theo type. Body: {type, enabled}
POST/reports/sites/bulk-update-promptsCập nhật prompt hàng loạt. Body: {site_names, prompt}
GET/reports/sites/statsThống kê tổng hợp sites
GET/reports/sites/:site_name/configFull config (prompt + gpt_config + response_config)
GET/reports/sites/:site_name/promptLấy prompt
PUT/reports/sites/:site_name/promptCập nhật prompt. Body: {prompt}
GET/reports/sites/:site_name/gpt-configLấy GPT config
PUT/reports/sites/:site_name/gpt-configCập nhật GPT config. Body: {model, temperature, max_tokens, response_format}
GET/reports/sites/:site_name/response-configLấy response config
PUT/reports/sites/:site_name/response-configCập nhật response config
GET/reports/vendors/enabledLấy email vendors đang enabled

Report Domains#

MethodEndpointMô tả
GET/reports/domainsDanh sách domains. Params: page, page_size, domain, keyword, type, status, exclude_deleted
GET/reports/domains/:idChi tiết domain + tất cả tasks liên kết
POST/reports/domainsThêm domain mới
GET/reports/statistics/dailyThống kê theo ngày/keyword. Default: 7 ngày gần nhất

Analytics#

MethodEndpointMô tả
GET/reports/analytics/keywordsPhân tích theo keyword. Params: keyword, page, page_size, start_date, end_date
GET/reports/analytics/top-keywordsTop keywords. Param: limit (max 20, default 5)
GET/reports/analytics/statsThống kê analytics tổng hợp

PC Report#

MethodEndpointMô tả
GET/reports/pc-reportJSON data cho tab Báo cáo PC
GET/reports/pc-report/csvExport CSV. Params: start_date, end_date, brand, format
GET/reports/pc-report/jsonJSON format cho PC report

Bulk Update#

MethodEndpointMô tả
POST/reports/bulk-updateCập nhật hàng loạt domains. Body: {ids: [], fields: {}}

IX. Pinia Store — reportStore#

File: admin/src/stores/reportStore.ts
Store global cho module Report, dùng bởi IndexView.vue thông qua storeToRefs:
reportStore.refreshAll(startTs, endTs, silent):
Gọi GET /reports/stats để cập nhật stats.
Param silent = true → không hiển thị loading spinner.

X. MongoDB Collections#

report_sites#

Collection lưu cấu hình các nền tảng báo cáo. Key tìm kiếm: name (indexed).

report_domains#

Collection lưu danh sách domain cần báo cáo. Key tìm kiếm: domain + keyword. Sort mặc định: created_at DESC.
Lưu ý: Record không bị xóa vật lý — chỉ được set status = "deleted".

report_tasks#

Collection lưu từng task báo cáo chi tiết. Mỗi domain × mỗi site = một task.
Quan trọng:
report_domain_id — Liên kết với report_domains._id (string, không phải ObjectID reference).
platform — Tên site (khớp với report_sites.name).
report_type — BROWSER_BASED hoặc EMAIL_BASED.
status — PENDING → IN_PROGRESS → COMPLETED / FAILED.
assigned_profile_id — Profile email được dùng để submit form.
server_id — Server thực thi task (liên kết MySQL servers.id).
result — Kết quả dạng JSON: { success, message, screenshot_url, report_id, ... }.

profiles#

Collection lưu browser profiles. Trong GetReportDomainByID, backend batch-fetch profiles để map assigned_profile_id → email.

XI. Service layer — 3 service instances#

Handler được inject với 3 service khác nhau:
ReportDashboardService — Service chính, xử lý:
Report sites CRUD (repos: reportSiteRepo → MongoDB report_sites)
Report domains CRUD (repos: MongoDB report_domains)
Report tasks queries (repos: reportTaskRepo → MongoDB report_tasks)
Cross-DB lookup: MySQL servers table qua mysqlClient
PCReportService — Service riêng cho tab Báo Cáo PC:
Tính toán stats từ MongoDB ads data.
Tổng hợp theo brand, daily stats.
Service (legacy) — Service cũ cho GeneratePCReport, vẫn dùng cho endpoint /pc-report/csv.

XII. Filtering và Phân trang#

Filtering trong SiteReportsTab#

useSiteReportsFiltering là computed property, filter phía client:
Khi currentTab = 'browser' → chỉ hiển thị type = BROWSER_BASED.
Khi currentTab = 'email' → chỉ hiển thị type = EMAIL_BASED.

Phân trang trong ReportDomainPool#

Server-side pagination, config mặc định:
Watch tự động trigger filter khi filters.type hoặc filters.status thay đổi (không cần click nút Filter).

Phân trang trong Tab Thống Kê#

Tasks list dùng server-side pagination. fetchDetailedStats dùng page_size=10000 để load toàn bộ rồi group phía client — đây là điểm cần lưu ý về hiệu năng khi data lớn.

XIII. Email Report Handler#

File: api/internal/report/handler/email_report_handler.go
Handler này sử dụng net/http standard library (KHÔNG dùng Fiber như các handler khác):
Các endpoint (chưa mount vào router chính, đang ở dạng standalone):
GET /api/reports/email/stats
GET /api/reports/email/stats/platform
GET /api/reports/email/stats/vendor
POST /api/reports/email/callback
GET /api/reports/email/tasks
GET /api/reports/email/tasks/{id}
GET /api/reports/email/analytics
Một số endpoint trả về placeholder data (hardcoded) vì chức năng chưa hoàn thiện. Ví dụ GetEmailReportTasks trả về mock task với platform KASPERSKY_EMAIL.
ProcessEmailReportCallback xử lý callback từ worker email:
1.
Parse task_id + result từ body.
2.
ValidateEmailReportResult(result) — kiểm tra dữ liệu hợp lệ.
3.
ProcessEmailReportTask(taskID, result) — update MongoDB.
4.
LogEmailReportResult(taskID, result) — ghi log debug.

XIV. Site full config flow (BROWSER_BASED)#

Khi worker cần xử lý một task BROWSER_BASED, nó cần biết cách điền form:
Worker gọi: GET /reports/sites/{site_name}/config
→ Trả về SiteFullConfigDTO:
  {
    site_name: "google_safe_browsing",
    prompt: "You are filling a phishing report form...",
    gpt_config: { model: "gpt-4o-mini", temperature: 0.1, max_tokens: 500, response_format: "json" },
    response_config: {
      required_fields: ["url", "description"],
      form_fields: {
        "url": { type: "text", required: true, max_length: 500 },
        "description": { type: "textarea", required: true, max_length: 2000 }
      }
    }
  }
Worker dùng thông tin này để:
1.
Truyền prompt + domain URL vào GPT API.
2.
GPT trả về JSON { "url": "...", "description": "..." }.
3.
Worker locate các input field trên trang web theo response_config.form_fields.
4.
Điền giá trị GPT trả về vào từng field.
5.
Submit form.
Caching: handler.go set Cache-Control: no-cache cho endpoint này để đảm bảo worker luôn lấy config mới nhất.

XV. Cấu trúc thư mục Frontend đầy đủ#

admin/src/views/report-dashboard/
├── IndexView.vue
├── composables/
│   ├── useReportDashboardData.ts
│   └── useReportDashboardOperations.ts
└── components/
    ├── report-dashboard/
    │   ├── ReportDashboardHeader.vue
    │   ├── ReportStatisticsTab.vue
    │   └── (sub-components chart, stats card...)
    ├── site-reports/
    │   ├── SiteReportsHeader.vue
    │   ├── SiteReportsStats.vue
    │   ├── SiteReportsFilters.vue
    │   ├── SiteReportCard.vue
    │   ├── SitePromptEditor.vue
    │   ├── BulkPromptUpdateModal.vue
    │   ├── CreateSiteModal.vue
    │   ├── EditSiteModal.vue
    │   └── composables/
    │       ├── useSiteReportsData.ts
    │       ├── useSiteReportsOperations.ts
    │       └── useSiteReportsFiltering.ts
    ├── report-domain-pool/
    │   ├── ReportDomainPoolHeader.vue
    │   ├── ReportDomainPoolStats.vue
    │   ├── ReportDomainPoolFilters.vue
    │   └── composables/
    │       ├── useReportDomainPoolColumns.ts
    │       ├── useReportDomainPoolData.ts
    │       └── useReportDomainPoolStats.ts
    ├── pc-report/
    │   ├── PCReportHeader.vue
    │   ├── SummaryStatisticsCard.vue
    │   ├── DailyStatsCard.vue
    │   ├── BrandStatisticsTable.vue
    │   ├── DailyStatisticsTable.vue
    │   └── composables/
    │       ├── usePCReportData.ts
    │       ├── usePCReportExport.ts
    │       └── usePCReportColumns.ts
    ├── SiteReportsTab.vue
    ├── ReportDomainPool.vue
    ├── PCReportDashboard.vue
    ├── TaskDetailModal.vue
    ├── DomainDetailModal.vue
    ├── AddDomainModal.vue
    ├── EditDomainModal.vue
    └── ViewDomainModal.vue

XVI. Cấu trúc thư mục Backend đầy đủ#

api/internal/report/
├── report.go              ← Structs: PCReportData, AdData, AccountData, ReportRequest
├── csv_generator.go       ← GeneratePCReportCSV, GenerateSimpleCSV
├── data_analysis.go       ← Utility functions phân tích dữ liệu
├── dto/                   ← Data Transfer Objects
├── handler/
│   ├── handler.go                        ← Route registration + Handler struct
│   ├── report_tasks_handlers.go          ← GetReportTasks, GetReportStats, GetChartData
│   ├── report_site_handlers.go           ← CRUD sites + toggle + bulk update prompt
│   ├── report_domain_handlers.go         ← CRUD domains + daily statistics
│   ├── report_analytics_handlers.go      ← Keyword analytics
│   ├── report_pc_handlers.go             ← PC Report JSON endpoint
│   ├── report_dashboard_handler.go       ← Handler struct definition
│   ├── report_task_monitoring_handlers.go
│   ├── report_utility_handlers.go
│   ├── request_report_task_handler.go    ← Worker task request endpoint
│   └── email_report_handler.go           ← Email callback (net/http)
├── model/
│   ├── report_site.go     ← ReportSite, GPTConfig, ResponseConfig, FieldConfig
│   └── report_domain.go   ← ReportDomain
├── service/
│   ├── service.go                    ← ReportDashboardService struct + DI
│   ├── report_sites.go               ← Site CRUD + toggle operations
│   ├── report_sites_defaults.go      ← 24 default sites (hardcoded)
│   ├── report_domains.go             ← Domain CRUD + status computation
│   ├── report_tasks.go               ← Task queries
│   ├── request_report_task.go        ← Worker task dispatch logic
│   ├── task_detail.go                ← Task detail with profile/server lookup
│   ├── task_monitoring.go            ← Active task monitoring
│   ├── email_report_service.go       ← Email-based report service
│   ├── pc_report.go                  ← PC Report aggregation (legacy)
│   ├── pc_report_service.go          ← PCReportService
│   ├── pc_report_calculator.go       ← Brand/daily stats calculation
│   ├── keyword_analytics.go          ← Keyword analytics
│   ├── report_stats.go               ← GetReportStats
│   └── ...các file helper khác
├── repository/            ← MongoDB repository layer
├── webhook/               ← Webhook callback handlers
├── cron/                  ← Cron jobs (task scheduling)
└── utils/                 ← Utility functions

XVII. Điểm quan trọng cần lưu ý#

1. site_name URL encoding:
Trong report_site_handlers.go, tất cả site_name param từ URL đều được decode qua url.QueryUnescape() trước khi xử lý. Điều này xử lý trường hợp tên site chứa ký tự đặc biệt khi truyền qua URL.
2. Task dispatch 3x multiplier:
RequestReportTask(serverIP, limit) tự động nhân limit lên 3 trước khi query:
Điều này cho phép tools_v2 nhận nhiều task hơn và tự quản lý concurrency.
3. Cross-database lookup trong task detail:
Khi lấy chi tiết domain (GetReportDomainByID), service thực hiện:
Lookup profiles (MongoDB) → lấy email từ assigned_profile_id.
Lookup servers (MySQL servers table) → lấy name và ip từ server_id.
Đây là cross-database operation, cần cả mongoDb và mysqlClient.
4. Platform display name caching:
Trong GetReportDomainByID, platformDisplayNameCache là map in-memory trong scope của một request để tránh query MongoDB nhiều lần cho cùng một platform name.
5. Status không phải ACID:
Trạng thái domain status được tính toán on-the-fly mỗi lần request từ trạng thái các tasks liên quan. Không có mechanism locking — nếu nhiều request đồng thời, có thể có race condition ngắn.

XVIII. GetWeeklyReportMetricsByKeywordAndDate Logic chi tiết#

Endpoint: GET /reports/statistics/daily
Handler: GetDailyStatistics
Service method: GetWeeklyReportMetricsByKeywordAndDate(ctx, startDate, endDate)
Đây là endpoint phức tạp nhất trong module Report, phục vụ cả biểu đồ tuần và bảng keyword statistics.

Date range logic trong handler#

Response structure#

{
  "success": true,
  "data": {
    "keywords": {
      "từ khóa A": {
        "total_processed": 20,
        "success_count": 10,
        "failure_count": 5,
        "dates": {
          "2026-03-17": {
            "total_processed": 5,
            "success_count": 3,
            "failure_count": 1
          }
        },
        "hours": {
          "0": { "success_count": 1, "failure_count": 0 },
          "14": { "success_count": 2, "failure_count": 1 }
        }
      },
      "từ khóa B": { ... }
    }
  }
}
Frontend tổng hợp tất cả keyword để vẽ biểu đồ:
Trục X: Ngày (dd/MM format)
Series 1 (xanh): Thành công SUM(success_count) qua tất cả keyword trong ngày đó
Series 2 (đỏ): Thất bại SUM(failure_count)
Series 3 (vàng): Đang chờ SUM(total_processed - success - failure)

XIX. Cron Job và Task Scheduling#

Thư mục: api/internal/report/cron/
Hệ thống cron quản lý việc tạo report tasks tự động:

Cơ chế hoạt động#

Cron job chạy theo lịch (thường là mỗi giờ hoặc mỗi ngày) để:
1.
Query report_domains với status = "ready".
2.
Với mỗi domain, query report_sites với enabled = true.
3.
Với mỗi cặp (domain, site), tạo một report_task mới trong MongoDB với:
status = "PENDING"
platform = site.name
report_type = site.type (BROWSER_BASED hoặc EMAIL_BASED)
domain = domain.domain
keyword = domain.keyword
scheduled_for = time.Now()
unique_key = domain + "|" + site.name + "|" + date
priority Ưu tiên xử lý (int, cao hơn = ưu tiên hơn)
4.
Cập nhật report_domains.status = "processing".
unique_key ngăn tạo task trùng lặp cho cùng một domain+site trong cùng một ngày.

Worker request flow#

tools_v2 Worker node (server 192.168.1.x)
  
POST /webhook/report/tasks?server_ip=192.168.1.x&limit=5
  
RequestReportTask(serverIP="192.168.1.x", limit=5)
  Request 15 tasks (53) từ MongoDB
  Filter: status=PENDING, sorted by priority DESC, created_at ASC
  Update: status=IN_PROGRESS, server_id=serverID
  
Return 15 task objects (sau khi validate bỏ garbage)
Mỗi task trong response có:
webhook_url URL để callback kết quả về: {WEBHOOK_HOST}/webhook/report/callback/report
proxy_url URL lấy proxy: {WEBHOOK_HOST}/webhook/check-ip
profile_url URL lấy profile: {WEBHOOK_HOST}/webhook/profile/get-random-profile?server_id=1&used_for=report

XX. Webhook Callback Report#

Endpoint: POST /webhook/report/callback/report
Thư mục: api/internal/report/webhook/
Khi worker hoàn thành một report task, nó POST callback với kết quả:

Request body (BROWSER_BASED)#

{
  "task_id": "680a1b2c3d4e5f6a7b8c9d0e",
  "status": "COMPLETED",
  "result": {
    "success": true,
    "message": "Report submitted successfully",
    "platform": "GOOGLE_SAFE_BROWSING",
    "report_type": "BROWSER_BASED",
    "submitted_at": "2026-03-23T07:00:00Z",
    "url": "https://malware-site.com",
    "report_id": "GS-12345",
    "response_time": 3200,
    "screenshot_url": "https://storage.example.com/screens/abc123.png",
    "screenshot_key": "screens/abc123.png"
  },
  "execution_time": 15000,
  "proxy_id": "proxy_abc123",
  "profile_id": "profile_xyz789"
}

Request body (EMAIL_BASED)#

{
  "task_id": "680a1b2c3d4e5f6a7b8c9d0f",
  "status": "COMPLETED",
  "result": {
    "success": true,
    "message": "Email reports sent to 2/3 recipients",
    "platform": "KASPERSKY_EMAIL",
    "report_type": "EMAIL_BASED",
    "submitted_at": "2026-03-23T07:00:00Z",
    "url": "https://malware-site.com",
    "email_recipients": ["newvirus@kaspersky.com", "virus@kaspersky.com"],
    "email_success_count": 2,
    "email_failure_count": 1,
    "email_results": [
      { "recipient": "newvirus@kaspersky.com", "success": true, "message_id": "msg-123" },
      { "recipient": "virus@kaspersky.com", "success": false, "error": "SMTP timeout" }
    ]
  }
}

Xử lý callback#

1.
Parse task_id Tìm task trong MongoDB.
2.
Update report_tasks:
status = COMPLETED / FAILED
completed_at = now
execution_time = result.executionTime
result = {...}
callback_sent = true
callback_sent_at = now
3.
Update report_sites.success_count++ hoặc failure_count++.
4.
Recalculate report_sites.success_rate.

XXI. Phân tích chi tiết ReportDomainByID#

GET /reports/domains/:id là endpoint phức tạp nhất vì nó join data từ nhiều nguồn:

Nguồn dữ liệu#

report_domains (MongoDB)
     có tasks liên kết
report_tasks (MongoDB)  JOIN qua report_domain_id HOẶC (domain + keyword)
     mỗi task có assigned_profile_id
profiles (MongoDB)  Batch lookup để lấy email
     mỗi task có server_id
servers (MySQL)  Lookup để lấy name + ip
     mỗi task có platform
report_sites (MongoDB)  Lookup display_name cho từng platform

Platform display name cache trong task detail#

Profile email priority#

Backend ưu tiên lấy email theo thứ tự:
1.
profileIDMap[task.AssignedProfileID] Email từ profiles collection (source of truth).
2.
task.Result["profile_email"] Email được lưu trong result (fallback).

XXII. Bulk Update Dashboard#

Endpoint: POST /reports/bulk-update
Body: { "ids": ["id1", "id2"], "fields": { "status": "deleted", "keyword": "..." } }
Dùng để cập nhật nhiều domain cùng lúc. Logic validation:
domain field: nếu có trong fields, phải bắt đầu bằng http:// hoặc https://.
updated_at được tự động thêm vào updateFields.
Nếu fields.status = "deleted" tự động gọi CancelTasksByDomainID cho từng domain.
Response:
{
  "success": true,
  "data": {
    "success_count": 2,
    "failed_count": 0,
    "failed_ids": [],
    "message": "Updated 2 records successfully"
  }
}

XXIII. Report phân loại theo cờ domain type#

type của report_domain ảnh hưởng đến cách Worker xử lý:
typeMô tảYêu cầu
google_adsDomain đang chạy Google Adskeyword bắt buộc
normalDomain thông thường (không qua tìm kiếm)keyword tùy chọn
Khi type = google_ads:
Worker tìm kiếm keyword trên Google trước.
Xác định domain trong kết quả tìm kiếm.
Ghi nhận context quảng cáo (screenshot, URL tracking).
Sau đó submit report với context này.
Khi type = normal:
Worker truy cập trực tiếp domain URL.
Thu thập bằng chứng vi phạm.
Submit report với direct URL.

XXIV. Thống kê tổng quan sites (GetSiteStats)#

Endpoint: GET /reports/sites/stats
Trả về:
{
  "total_sites": 24,
  "active_sites": 18,
  "inactive_sites": 6,
  "success_rate": 87.5,
  "total_reports": 945,
  "success_reports": 827,
  "failure_reports": 118
}
Query MongoDB report_tasks:
Đây là tổng không phân biệt ngày tất cả tasks trong lịch sử.

XXV. SiteReportCard Chi tiết card hiển thị#

Mỗi SiteReportCard.vue hiển thị:
Icon (MDI) + Display name + category badge
Toggle switch (bật/tắt) gọi operations.toggleSite(site)
Success rate badge (màu theo threshold)
Success count + Failure count
Nút Sửa Prompt mở SitePromptEditor
Nút Sửa mở EditSiteModal
Nút Xóa dialog xác nhận DELETE /reports/sites/:site_name
toggleSite gọi POST /reports/sites/toggle:

XXVI. SitePromptEditor Modal#

File: components/site-reports/SitePromptEditor.vue
Modal editor cho phép admin viết AI prompt cho từng site báo cáo.
Flow:
1.
Admin click "Sửa Prompt" trên SiteReportCard.
2.
handleEditPrompt(site) set selectedSite, mở showPromptEditor.
3.
SitePromptEditor load prompt hiện tại: GET /reports/sites/:site_name/prompt.
4.
Hiển thị textarea để chỉnh sửa.
5.
Save: PUT /reports/sites/:site_name/prompt { prompt: "..." }.
6.
Emit saved parent gọi data.fetchSites() để refresh.
Prompt format ví dụ (Google Safe Browsing):
You are a security analyst filling out a phishing report form.
The domain {domain} has been identified as a phishing site targeting {keyword}.
Fill in the following fields:
- url: The full URL of the phishing site
- description: Brief description of why this site is phishing
- category: "PHISHING" or "MALWARE"

XXVII. BulkPromptUpdateModal#

File: components/site-reports/BulkPromptUpdateModal.vue
Cho phép áp dụng cùng một prompt cho nhiều sites cùng lúc:
1.
Modal hiển thị danh sách checkboxes tất cả sites.
2.
Admin chọn sites muốn cập nhật.
3.
Nhập prompt chung vào textarea.
4.
Submit: POST /reports/sites/bulk-update-prompts
{ "site_names": ["google_safe_browsing", "spamhaus"], "prompt": "..." }
5.
Response trả về updated_count.
6.
Parent emit saved(updatedCount) nếu updatedCount > 0 refetch sites.

XXVIII. Enabled Vendors API#

Endpoint: GET /reports/vendors/enabled
Handler: GetEnabledVendors
Trả về danh sách tất cả EMAIL_BASED sites đang enabled = true và status = "active".
Query MongoDB:
Dùng bởi Email Report service để xác định cần gửi email đến những địa chỉ nào khi xử lý EMAIL_BASED task.

XXIX. Monitoring và Debug#

Task Monitoring#

Endpoint: GET /reports/tasks/monitoring
Handler: GetTaskMonitoring
File service: api/internal/report/service/task_monitoring.go
Trả về snapshot trạng thái hiện tại:
Số task PENDING
Số task IN_PROGRESS
Số task COMPLETED trong 24h qua
Số task FAILED trong 24h qua
Breakdown theo platform
Danh sách tasks bị stuck (IN_PROGRESS > 30 phút)

Active Tasks#

Endpoint: GET /reports/tasks/active
Trả về danh sách tasks đang có status = IN_PROGRESS, kèm thông tin:
domain, platform, server_id, started_at
execution_time (giây kể từ started_at)
Dùng để phát hiện worker bị treo (task IN_PROGRESS quá lâu).

Task Detail#

Endpoint: GET /reports/tasks/:id
Trả về đầy đủ thông tin một task bao gồm:
Metadata (domain, keyword, platform, type)
Timing (created_at, started_at, completed_at, execution_time)
Assignment (server, proxy, profile)
Result (success/fail, screenshot, report_id)
GPT data (gpt_raw_prompt raw prompt đã gửi cho GPT)
gpt_raw_prompt Lưu lại raw prompt đã thực sự gửi cho model GPT (sau khi đã inject domain, keyword vào template). Dùng để debug khi GPT trả về output sai.

XXX. Điểm khác biệt giữa các service instances#

ReportDashboardService (service chính)#

Được inject cả:
mongoDb MongoDB connection
mysqlClient GORM MySQL client (dùng cho server lookup)
reportSiteRepo MongoDB repo cho report_sites
reportTaskRepo MongoDB repo cho report_tasks

PCReportService (service Báo Cáo PC)#

Chỉ dùng MongoDB. Tập trung vào aggregation dữ liệu ads:
ads_metrics_service.go Aggregate metrics từ ads collection
account_metrics_service.go Tính dead/alive accounts
brand_extractor.go Phân loại brand từ domain/keyword

Service (legacy)#

Còn tồn tại để backward compatible với endpoint /pc-report/csv. Sử dụng csv_generator.go để tạo file CSV.
csv_generator.go tạo CSV với các cột:
Report Date | Brand | Ads Detected | Reports Count | New Dead Ads |
Remaining Ads | Ad Accounts | Remaining Accounts | Dead Accounts | Dead % |
Success Rate | Failure Rate | Keywords Count | Active Keywords

XXXI. Xử lý lỗi và Edge Cases#

1. Site không tìm thấy trong GetSiteFullConfig:
Handler trả về danh sách tất cả available sites để debug:
2. Task với domain rỗng:
RequestReportTask bỏ qua task có domain rỗng thay vì trả lỗi:
3. Empty keyword default:
Nếu task có keyword rỗng tự động set keyword = "unknown" thay vì bỏ qua.
4. Concurrent fetch guard:
useReportDashboardData dùng module-level booleans không phải ref:
Cách này hoạt động vì JavaScript single-threaded, nhưng cần chú ý nếu refactor sang async/await phức tạp hơn.
5. Report task unique_key:
Mỗi task có unique_key = domain + "|" + site.name + "|" + date để tránh submit trùng lặp trong cùng ngày. Cron job check key này trước khi tạo task mới.
6. EmailReportHandler dùng net/http thay vì Fiber:
Email handler được viết với standard library, chưa được mount vào Fiber router. Đây có thể là code cũ hoặc đang trong quá trình migration.
Modified at 2026-03-23 05:18:37
Previous
3. Tìm kiếm tự động (Automated Discovery)
Next
5. Quản lý tài khoản (Account Management)
Built with