crm/frontend/js/trial-periods-page.js
2026-01-13 18:02:43 +08:00

411 lines
14 KiB
JavaScript

// Trial Periods Page Management
// This file handles the standalone trial periods page
let trialPeriodsData = [];
let trialCurrentPage = 1;
let trialPageSize = 10;
let trialTotalItems = 0;
let trialTotalPages = 0;
let customersMap = {}; // Map of customer ID to customer name
// Initialize trial periods page
function initTrialPeriodsPage() {
const addTrialBtn = document.getElementById('addTrialBtn');
const trialPeriodsSection = document.getElementById('trialPeriodsSection');
if (!trialPeriodsSection) return;
// Add trial button click
if (addTrialBtn) {
addTrialBtn.addEventListener('click', function () {
openAddTrialModal();
});
}
// Pagination controls
document.getElementById('trialFirstPage')?.addEventListener('click', () => {
trialCurrentPage = 1;
loadAllTrialPeriods();
});
document.getElementById('trialPrevPage')?.addEventListener('click', () => {
if (trialCurrentPage > 1) {
trialCurrentPage--;
loadAllTrialPeriods();
}
});
document.getElementById('trialNextPage')?.addEventListener('click', () => {
if (trialCurrentPage < trialTotalPages) {
trialCurrentPage++;
loadAllTrialPeriods();
}
});
document.getElementById('trialLastPage')?.addEventListener('click', () => {
trialCurrentPage = trialTotalPages;
loadAllTrialPeriods();
});
document.getElementById('trialPageSizeSelect')?.addEventListener('change', function () {
trialPageSize = parseInt(this.value);
trialCurrentPage = 1;
loadAllTrialPeriods();
});
// Load customers for dropdown
loadCustomersForDropdown();
}
// Load all customers for dropdown
async function loadCustomersForDropdown() {
try {
console.log('Loading customers for dropdown...');
const response = await authenticatedFetch('/api/customers/list');
if (!response) {
console.error('No response from API');
return;
}
const data = await response.json();
console.log('Customers data:', data);
const customers = data.customers || [];
console.log('Number of customers:', customers.length);
customersMap = {};
const select = document.getElementById('trialCustomerSelect');
if (!select) {
console.error('trialCustomerSelect element not found');
return;
}
// Keep the first option (请选择客户)
select.innerHTML = '<option value="">请选择客户</option>';
customers.forEach(customer => {
customersMap[customer.id] = customer.customerName;
const option = document.createElement('option');
option.value = customer.id;
option.textContent = customer.customerName;
select.appendChild(option);
});
console.log('Customers loaded successfully. Total:', customers.length);
} catch (error) {
console.error('Error loading customers:', error);
}
}
// Load all trial periods
async function loadAllTrialPeriods() {
try {
const response = await authenticatedFetch('/api/trial-periods/all');
const data = await response.json();
trialPeriodsData = data.trialPeriods || [];
trialTotalItems = trialPeriodsData.length;
trialTotalPages = Math.ceil(trialTotalItems / trialPageSize);
renderTrialPeriodsTable();
updateTrialPagination();
} catch (error) {
console.error('Error loading trial periods:', error);
trialPeriodsData = [];
renderTrialPeriodsTable();
}
}
// Render expiry warning cards
function renderExpiryWarnings() {
const warningsContainer = document.getElementById('trialExpiryWarnings');
if (!warningsContainer) return;
warningsContainer.innerHTML = '';
const now = new Date();
now.setHours(0, 0, 0, 0); // Set to start of today
const warnings = [];
trialPeriodsData.forEach(period => {
const endTime = new Date(period.endTime);
endTime.setHours(0, 0, 0, 0); // Set to start of day
const daysUntilExpiry = Math.ceil((endTime - now) / (1000 * 60 * 60 * 24));
const customerName = customersMap[period.customerId] || period.customerId;
if (daysUntilExpiry >= 0 && daysUntilExpiry <= 3) {
warnings.push({
customerName,
endTime: period.endTime,
daysUntilExpiry,
period
});
}
});
// Sort by days until expiry (most urgent first)
warnings.sort((a, b) => a.daysUntilExpiry - b.daysUntilExpiry);
warnings.forEach(warning => {
const card = document.createElement('div');
let warningClass = 'warning-soon';
let iconClass = 'fa-info-circle';
let title = '试用即将到期';
let message = '';
if (warning.daysUntilExpiry === 0) {
warningClass = 'warning-today';
iconClass = 'fa-exclamation-triangle';
title = '试用今日到期';
message = `<strong>${warning.customerName}</strong> 客户的试用期将于<span class="expiry-warning-time">今天</span>到期,请及时跟进!`;
} else if (warning.daysUntilExpiry === 1) {
warningClass = 'warning-tomorrow';
iconClass = 'fa-exclamation-circle';
title = '试用明日到期';
message = `<strong>${warning.customerName}</strong> 客户的试用期将于<span class="expiry-warning-time">明天</span>到期,请及时跟进!`;
} else {
warningClass = 'warning-soon';
iconClass = 'fa-info-circle';
title = '试用即将到期';
message = `<strong>${warning.customerName}</strong> 客户的试用期将于<span class="expiry-warning-time">${warning.daysUntilExpiry}天后</span>到期,请及时跟进!`;
}
const formattedEndTime = formatDateTime(warning.endTime);
message += `<br><small>试用结束时间:${formattedEndTime}</small>`;
card.className = `expiry-warning-card ${warningClass}`;
card.innerHTML = `
<div class="expiry-warning-icon">
<i class="fas ${iconClass}"></i>
</div>
<div class="expiry-warning-content">
<div class="expiry-warning-title">${title}</div>
<div class="expiry-warning-message">${message}</div>
</div>
<button class="expiry-warning-close" onclick="this.parentElement.remove()">
<i class="fas fa-times"></i>
</button>
`;
warningsContainer.appendChild(card);
});
}
// Render trial periods table
function renderTrialPeriodsTable() {
const tbody = document.getElementById('trialPeriodsBody');
if (!tbody) return;
tbody.innerHTML = '';
if (trialPeriodsData.length === 0) {
const row = document.createElement('tr');
row.innerHTML = '<td colspan="5" style="text-align: center; padding: 30px; color: #999;">暂无试用时间记录</td>';
tbody.appendChild(row);
return;
}
// Paginate data
const startIndex = (trialCurrentPage - 1) * trialPageSize;
const endIndex = Math.min(startIndex + trialPageSize, trialPeriodsData.length);
const pageData = trialPeriodsData.slice(startIndex, endIndex);
pageData.forEach(period => {
const row = document.createElement('tr');
const customerName = customersMap[period.customerId] || period.customerId;
const startTime = formatDateTime(period.startTime);
const endTime = formatDateTime(period.endTime);
const createdAt = formatDateTime(period.createdAt);
row.innerHTML = `
<td>${customerName}</td>
<td>${startTime}</td>
<td>${endTime}</td>
<td>${createdAt}</td>
<td>
<button class="action-btn edit-btn" data-id="${period.id}" title="编辑">
<i class="fas fa-edit"></i>
</button>
<button class="action-btn delete-btn" data-id="${period.id}" title="删除">
<i class="fas fa-trash"></i>
</button>
</td>
`;
tbody.appendChild(row);
});
// Add event listeners
tbody.querySelectorAll('.edit-btn').forEach(btn => {
btn.addEventListener('click', function () {
const periodId = this.getAttribute('data-id');
openEditTrialModal(periodId);
});
});
tbody.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', function () {
const periodId = this.getAttribute('data-id');
deleteTrialPeriodFromPage(periodId);
});
});
}
// Update trial pagination
function updateTrialPagination() {
const startItem = trialTotalItems === 0 ? 0 : (trialCurrentPage - 1) * trialPageSize + 1;
const endItem = Math.min(trialCurrentPage * trialPageSize, trialTotalItems);
document.getElementById('trialPaginationInfo').textContent =
`显示 ${startItem}-${endItem}${trialTotalItems}`;
document.getElementById('trialFirstPage').disabled = trialCurrentPage === 1;
document.getElementById('trialPrevPage').disabled = trialCurrentPage === 1;
document.getElementById('trialNextPage').disabled = trialCurrentPage === trialTotalPages;
document.getElementById('trialLastPage').disabled = trialCurrentPage === trialTotalPages;
// Update page numbers
const pageNumbers = document.getElementById('trialPageNumbers');
pageNumbers.innerHTML = '';
const maxVisiblePages = 5;
let startPage = Math.max(1, trialCurrentPage - Math.floor(maxVisiblePages / 2));
let endPage = Math.min(trialTotalPages, startPage + maxVisiblePages - 1);
if (endPage - startPage < maxVisiblePages - 1) {
startPage = Math.max(1, endPage - maxVisiblePages + 1);
}
for (let i = startPage; i <= endPage; i++) {
const pageBtn = document.createElement('button');
pageBtn.className = 'page-number';
if (i === trialCurrentPage) {
pageBtn.classList.add('active');
}
pageBtn.textContent = i;
pageBtn.addEventListener('click', () => {
trialCurrentPage = i;
loadAllTrialPeriods();
});
pageNumbers.appendChild(pageBtn);
}
}
// Open add trial modal
function openAddTrialModal() {
console.log('Opening add trial modal');
// Load customers first
loadCustomersForDropdown().then(() => {
console.log('Customers loaded, opening modal');
document.getElementById('trialCustomerSelect').value = '';
document.getElementById('trialStartTime').value = '';
document.getElementById('trialEndTime').value = '';
document.getElementById('addTrialPeriodModal').style.display = 'block';
});
}
// Open edit trial modal
function openEditTrialModal(periodId) {
const period = trialPeriodsData.find(p => p.id === periodId);
if (!period) return;
document.getElementById('editTrialPeriodId').value = period.id;
const startDate = new Date(period.startTime);
const endDate = new Date(period.endTime);
document.getElementById('editTrialStartTime').value = formatDateTimeLocal(startDate);
document.getElementById('editTrialEndTime').value = formatDateTimeLocal(endDate);
document.getElementById('editTrialPeriodModal').style.display = 'block';
}
// Delete trial period from page
async function deleteTrialPeriodFromPage(periodId) {
if (!confirm('确定要删除这个试用时间记录吗?')) {
return;
}
try {
const response = await authenticatedFetch(`/api/trial-periods/${periodId}`, {
method: 'DELETE'
});
if (response.ok) {
await loadAllTrialPeriods();
alert('试用时间删除成功!');
} else {
alert('删除试用时间时出错');
}
} catch (error) {
console.error('Error deleting trial period:', error);
alert('删除试用时间时出错');
}
}
// Create trial period from page
async function createTrialPeriodFromPage() {
const customerId = document.getElementById('trialCustomerSelect').value;
const startTime = document.getElementById('trialStartTime').value;
const endTime = document.getElementById('trialEndTime').value;
if (!customerId) {
alert('请选择客户');
return;
}
if (!startTime || !endTime) {
alert('请填写开始时间和结束时间');
return;
}
const formData = {
customerId: customerId,
startTime: new Date(startTime).toISOString(),
endTime: new Date(endTime).toISOString()
};
try {
const response = await authenticatedFetch('/api/trial-periods', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
if (response.ok) {
document.getElementById('addTrialPeriodModal').style.display = 'none';
document.getElementById('addTrialPeriodForm').reset();
await loadAllTrialPeriods();
alert('试用时间添加成功!');
} else {
alert('添加试用时间时出错');
}
} catch (error) {
console.error('Error creating trial period:', error);
alert('添加试用时间时出错');
}
}
// Initialize when switching to trial periods section
document.addEventListener('DOMContentLoaded', function () {
initTrialPeriodsPage();
// Override the form submit for add trial period
const addForm = document.getElementById('addTrialPeriodForm');
if (addForm) {
addForm.addEventListener('submit', async function (e) {
e.preventDefault();
await createTrialPeriodFromPage();
});
}
});