File manager - Edit - /home/webapp69.cm.in.th/u69319090028/Shop/views/admin/reviews/index.php
Back
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3 mb-4"> <div> <h4 class="fw-bold text-dark mb-1"> <i class="bi bi-shield-check text-primary me-2"></i>จัดการและกลั่นกรองรีวิว (Review Moderation) </h4> <p class="text-muted small mb-0">ตรวจสอบ ตรวจตราความเหมาะสม และกลั่นกรองรีวิวสินค้าจากลูกค้าทั่วทั้งมาร์เก็ตเพลส</p> </div> </div> <!-- 1. KPI Statistics --> <div class="row g-3 mb-4"> <div class="col-6 col-lg-3"> <div class="card border-0 shadow-sm p-3 h-100"> <div class="d-flex align-items-center gap-3"> <div class="rounded-3 bg-primary-subtle text-primary p-3 d-flex align-items-center justify-content-center"> <i class="bi bi-chat-square-text fs-4"></i> </div> <div> <span class="text-muted small fw-semibold">รีวิวทั้งหมด</span> <h4 class="fw-bold text-dark mb-0"><?= number_format($stats['total_reviews']) ?></h4> </div> </div> </div> </div> <div class="col-6 col-lg-3"> <div class="card border-0 shadow-sm p-3 h-100"> <div class="d-flex align-items-center gap-3"> <div class="rounded-3 bg-success-subtle text-success p-3 d-flex align-items-center justify-content-center"> <i class="bi bi-check-circle fs-4"></i> </div> <div> <span class="text-muted small fw-semibold">แสดงผลปกติ (Active)</span> <h4 class="fw-bold text-success mb-0"><?= number_format($stats['active_count']) ?></h4> </div> </div> </div> </div> <div class="col-6 col-lg-3"> <div class="card border-0 shadow-sm p-3 h-100"> <div class="d-flex align-items-center gap-3"> <div class="rounded-3 bg-warning-subtle text-warning p-3 d-flex align-items-center justify-content-center"> <i class="bi bi-eye-slash fs-4"></i> </div> <div> <span class="text-muted small fw-semibold">ถูกซ่อน (Hidden)</span> <h4 class="fw-bold text-warning mb-0"><?= number_format($stats['hidden_count']) ?></h4> </div> </div> </div> </div> <div class="col-6 col-lg-3"> <div class="card border-0 shadow-sm p-3 h-100"> <div class="d-flex align-items-center gap-3"> <div class="rounded-3 bg-info-subtle text-info p-3 d-flex align-items-center justify-content-center"> <i class="bi bi-star-half fs-4"></i> </div> <div> <span class="text-muted small fw-semibold">คะแนนเฉลี่ยระบบ</span> <h4 class="fw-bold text-dark mb-0"><?= number_format($stats['platform_avg_rating'], 2) ?> <small class="text-muted fs-6">/ 5</small></h4> </div> </div> </div> </div> </div> <!-- 2. Filter Bar --> <div class="card border-0 shadow-sm mb-4"> <div class="card-body p-3"> <form action="<?= url('/admin/reviews') ?>" method="GET" class="row g-2 align-items-end"> <div class="col-md-3"> <label class="form-label small fw-bold text-muted mb-1">ค้นหา (สินค้า, ร้านค้า, ผู้ใช้, ข้อความ)</label> <input type="text" name="q" class="form-control form-control-sm" placeholder="พิมพ์คำค้นหา..." value="<?= e($filters['q'] ?? '') ?>"> </div> <div class="col-md-2"> <label class="form-label small fw-bold text-muted mb-1">สถานะรีวิว</label> <select name="status" class="form-select form-select-sm"> <option value="all">ทุกสถานะ</option> <option value="active" <?= ($filters['status'] ?? '') === 'active' ? 'selected' : '' ?>>Active (แสดงผล)</option> <option value="hidden" <?= ($filters['status'] ?? '') === 'hidden' ? 'selected' : '' ?>>Hidden (ซ่อน)</option> <option value="removed" <?= ($filters['status'] ?? '') === 'removed' ? 'selected' : '' ?>>Removed (ลบแล้ว)</option> </select> </div> <div class="col-md-2"> <label class="form-label small fw-bold text-muted mb-1">คะแนนดาว</label> <select name="rating" class="form-select form-select-sm"> <option value="0">ดาวทั้งหมด</option> <option value="5" <?= ($filters['rating'] ?? 0) === 5 ? 'selected' : '' ?>>5 ดาว</option> <option value="4" <?= ($filters['rating'] ?? 0) === 4 ? 'selected' : '' ?>>4 ดาว</option> <option value="3" <?= ($filters['rating'] ?? 0) === 3 ? 'selected' : '' ?>>3 ดาว</option> <option value="2" <?= ($filters['rating'] ?? 0) === 2 ? 'selected' : '' ?>>2 ดาว</option> <option value="1" <?= ($filters['rating'] ?? 0) === 1 ? 'selected' : '' ?>>1 ดาว</option> </select> </div> <div class="col-md-3"> <label class="form-label small fw-bold text-muted mb-1">ช่วงวันที่</label> <div class="input-group input-group-sm"> <input type="date" name="date_from" class="form-control" value="<?= e($filters['date_from'] ?? '') ?>"> <span class="input-group-text bg-light">-</span> <input type="date" name="date_to" class="form-control" value="<?= e($filters['date_to'] ?? '') ?>"> </div> </div> <div class="col-md-2 d-flex gap-2"> <button type="submit" class="btn btn-primary btn-sm flex-grow-1"> <i class="bi bi-search me-1"></i> ค้นหา </button> <a href="<?= url('/admin/reviews') ?>" class="btn btn-outline-secondary btn-sm" title="ล้างตัวกรอง"> <i class="bi bi-arrow-clockwise"></i> </a> </div> </form> </div> </div> <!-- 3. Reviews Moderation Table --> <div class="card border-0 shadow-sm overflow-hidden"> <div class="card-header bg-white py-3 border-bottom d-flex justify-content-between align-items-center"> <h6 class="fw-bold text-dark mb-0 small"> <i class="bi bi-list-check me-1 text-primary"></i> รายการรีวิวในระบบ (<?= number_format($totalCount) ?> รายการ) </h6> </div> <div class="table-responsive"> <table class="table table-hover align-middle mb-0 small"> <thead class="table-light text-muted"> <tr> <th style="width: 50px;">#</th> <th>ผู้รีวิว</th> <th>สินค้า & ร้านค้า</th> <th style="width: 120px;">คะแนน</th> <th style="min-width: 250px;">ข้อความรีวิว & รูปภาพ</th> <th style="width: 100px;">สถานะ</th> <th style="width: 130px;">วันที่</th> <th style="width: 110px;" class="text-end pe-3">จัดการ</th> </tr> </thead> <tbody> <?php if (empty($reviews)): ?> <tr> <td colspan="8" class="text-center py-5 text-muted"> <i class="bi bi-inbox fs-2 d-block mb-2"></i> ไม่พบข้อมูลรีวิวตามเงื่อนไขที่กำหนด </td> </tr> <?php else: ?> <?php foreach ($reviews as $rev): ?> <tr> <td class="text-muted fw-semibold">#<?= (int)$rev['id'] ?></td> <td> <div class="fw-semibold text-dark"><?= e($rev['display_name']) ?></div> <small class="text-muted">@<?= e($rev['username'] ?? '') ?></small> <?php if (!empty($rev['is_anonymous'])): ?> <span class="badge bg-light text-muted border small d-block mt-1" style="font-size: 0.65rem; width: fit-content;"> <i class="bi bi-incognito"></i> ไม่ระบุชื่อ </span> <?php endif; ?> </td> <td> <a href="<?= url('/product/' . (int)$rev['product_id']) ?>" target="_blank" class="fw-semibold text-dark text-decoration-none d-block text-truncate" style="max-width: 220px;"> <?= e($rev['product_name']) ?> </a> <small class="text-muted"> <i class="bi bi-shop me-1"></i><?= e($rev['store_name']) ?> • <code>#<?= e($rev['order_no']) ?></code> </small> </td> <td> <div class="d-flex align-items-center gap-1"> <?php for ($s = 1; $s <= 5; $s++): ?> <i class="bi <?= $s <= (int)$rev['rating'] ? 'bi-star-fill text-warning' : 'bi-star text-secondary' ?>" style="font-size: 0.75rem;"></i> <?php endfor; ?> </div> <span class="fw-bold text-dark small"><?= (int)$rev['rating'] ?>.0 ดาว</span> </td> <td> <?php if (!empty($rev['review_text'])): ?> <div class="text-secondary mb-2" style="max-height: 80px; overflow-y: auto; white-space: pre-line;"> <?= e($rev['review_text']) ?> </div> <?php else: ?> <span class="text-muted fst-italic">ไม่มีข้อความ</span> <?php endif; ?> <?php if (!empty($rev['images'])): ?> <div class="d-flex flex-wrap gap-1"> <?php foreach ($rev['images'] as $img): ?> <a href="<?= asset('/' . ltrim($img['image_path'], '/')) ?>" target="_blank" class="rounded-1 overflow-hidden border bg-light d-inline-block" style="width: 36px; height: 36px;"> <img src="<?= asset('/' . ltrim($img['image_path'], '/')) ?>" class="w-100 h-100 object-fit-cover"> </a> <?php endforeach; ?> </div> <?php endif; ?> <?php if (!empty($rev['admin_notes'])): ?> <div class="mt-2 p-2 bg-light rounded text-muted" style="font-size: 0.7rem;"> <i class="bi bi-journal-text me-1"></i><strong>Admin Note:</strong> <?= e($rev['admin_notes']) ?> </div> <?php endif; ?> </td> <td> <?php if ($rev['status'] === 'active'): ?> <span class="badge bg-success-subtle text-success border border-success-subtle px-2 py-1"> <i class="bi bi-check-circle me-1"></i>Active </span> <?php elseif ($rev['status'] === 'hidden'): ?> <span class="badge bg-warning-subtle text-warning border border-warning-subtle px-2 py-1"> <i class="bi bi-eye-slash me-1"></i>Hidden </span> <?php else: ?> <span class="badge bg-danger-subtle text-danger border border-danger-subtle px-2 py-1"> <i class="bi bi-x-circle me-1"></i>Removed </span> <?php endif; ?> </td> <td class="text-muted"> <?= date('d/m/Y', strtotime($rev['created_at'])) ?><br> <small><?= date('H:i', strtotime($rev['created_at'])) ?></small> </td> <td class="text-end pe-3"> <div class="dropdown"> <button class="btn btn-outline-secondary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown"> จัดการ </button> <ul class="dropdown-menu dropdown-menu-end shadow-sm border small"> <?php if ($rev['status'] === 'active'): ?> <li> <button type="button" class="dropdown-item text-warning btn-moderate-action" data-id="<?= (int)$rev['id'] ?>" data-action="hide" data-action-text="ซ่อนรีวิวนี้ (จะไม่แสดงต่อผู้ซื้อและไม่นำมาคำนวณคะแนน)"> <i class="bi bi-eye-slash me-2"></i> ซ่อนรีวิว (Hide) </button> </li> <li> <button type="button" class="dropdown-item text-danger btn-moderate-action" data-id="<?= (int)$rev['id'] ?>" data-action="remove" data-action-text="ลบรีวิวนี้ออกจากระบบอย่างถาวร"> <i class="bi bi-trash me-2"></i> ลบรีวิว (Remove) </button> </li> <?php elseif ($rev['status'] === 'hidden'): ?> <li> <button type="button" class="dropdown-item text-success btn-moderate-action" data-id="<?= (int)$rev['id'] ?>" data-action="restore" data-action-text="คืนสถานะรีวิวให้แสดงผลและนำมาคำนวณคะแนนตามปกติ"> <i class="bi bi-check-circle me-2"></i> คืนสถานะ (Restore) </button> </li> <li> <button type="button" class="dropdown-item text-danger btn-moderate-action" data-id="<?= (int)$rev['id'] ?>" data-action="remove" data-action-text="ลบรีวิวนี้ออกจากระบบอย่างถาวร"> <i class="bi bi-trash me-2"></i> ลบรีวิว (Remove) </button> </li> <?php elseif ($rev['status'] === 'removed'): ?> <li> <button type="button" class="dropdown-item text-success btn-moderate-action" data-id="<?= (int)$rev['id'] ?>" data-action="restore" data-action-text="คืนสถานะรีวิวกลับมาใช้งาน"> <i class="bi bi-arrow-counterclockwise me-2"></i> คืนสถานะ (Restore) </button> </li> <?php endif; ?> </ul> </div> </td> </tr> <?php endforeach; ?> <?php endif; ?> </tbody> </table> </div> <!-- Pagination --> <?php if ($totalPages > 1): ?> <div class="card-footer bg-white py-3 d-flex justify-content-between align-items-center"> <small class="text-muted">หน้า <?= $currentPage ?> จาก <?= $totalPages ?> (รวม <?= number_format($totalCount) ?> รายการ)</small> <ul class="pagination pagination-sm mb-0"> <?php for ($p = 1; $p <= $totalPages; $p++): ?> <?php $queryParams = array_merge($_GET, ['page' => $p]); $pageUrl = url('/admin/reviews') . '?' . http_build_query($queryParams); ?> <li class="page-item <?= $p === $currentPage ? 'active' : '' ?>"> <a class="page-link" href="<?= $pageUrl ?>"><?= $p ?></a> </li> <?php endfor; ?> </ul> </div> <?php endif; ?> </div> <!-- Moderation Modal --> <div class="modal fade" id="moderationModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content border-0 shadow"> <form action="<?= url('/admin/reviews/moderate') ?>" method="POST" id="moderationForm"> <?= Security::csrfField() ?> <input type="hidden" name="review_id" id="modalReviewId"> <input type="hidden" name="action" id="modalAction"> <div class="modal-header border-bottom"> <h6 class="modal-title fw-bold text-dark" id="modalTitle"> <i class="bi bi-shield-exclamation text-warning me-2"></i>ยืนยันการกลั่นกรองรีวิว </h6> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body p-4"> <div class="alert alert-info py-2 px-3 small mb-3" id="modalActionDesc"></div> <div class="mb-3"> <label for="modalReason" class="form-label fw-bold small text-dark"> เหตุผลการดำเนินการ <span class="text-danger">*</span> </label> <textarea name="reason" id="modalReason" class="form-control form-control-sm" rows="3" placeholder="ระบุเหตุผล เช่น มีข้อความหยาบคาย, รีวิวไม่เกี่ยวกับสินค้า, มีลิงก์ภายนอก..." required></textarea> <div class="form-text small">เหตุผลนี้จะถูกบันทึกในระบบ Admin Audit Log เพื่อความโปร่งใสและตรวจสอบย้อนหลังได้</div> </div> </div> <div class="modal-footer border-top py-2"> <button type="button" class="btn btn-outline-secondary btn-sm px-3" data-bs-dismiss="modal">ยกเลิก</button> <button type="submit" class="btn btn-primary btn-sm px-4 fw-bold" id="btnConfirmModerate"> <i class="bi bi-check-lg me-1"></i> ยืนยันการดำเนินการ </button> </div> </form> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const modalElem = document.getElementById('moderationModal'); const modal = new bootstrap.Modal(modalElem); const modalReviewId = document.getElementById('modalReviewId'); const modalAction = document.getElementById('modalAction'); const modalActionDesc = document.getElementById('modalActionDesc'); const modalReason = document.getElementById('modalReason'); document.querySelectorAll('.btn-moderate-action').forEach(btn => { btn.addEventListener('click', function() { const reviewId = this.getAttribute('data-id'); const action = this.getAttribute('data-action'); const desc = this.getAttribute('data-action-text'); modalReviewId.value = reviewId; modalAction.value = action; modalActionDesc.textContent = desc; modalReason.value = ''; if (action === 'restore') { modalReason.required = false; modalReason.placeholder = 'ระบุเหตุผล (ไม่บังคับ)...'; } else { modalReason.required = true; modalReason.placeholder = 'ระบุเหตุผลที่ชัดเจน...'; } modal.show(); }); }); }); </script>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.24 |
proxy
|
phpinfo
|
Settings