crm/frontend/js/trial-periods-page.js
2026-01-14 20:31:08 +08:00

413 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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();
renderExpiryWarnings();
} 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');
// 显示客户名称如果找不到则显示ID
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();
});
}
});