crm/frontend/js/trial-periods-page.js

828 lines
31 KiB
JavaScript
Raw Permalink 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 filteredTrialPeriodsData = [];
let trialCurrentPage = 1;
let trialPageSize = 10;
let trialTotalItems = 0;
let trialTotalPages = 0;
let customersMap = {}; // Map of customer ID to customer name
let trialStartDateFilter = '';
let trialEndDateFilter = '';
let trialSortOrder = 'createdAtDesc';
// 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;
applyTrialFiltersAndSort();
});
document.getElementById('trialPrevPage')?.addEventListener('click', () => {
if (trialCurrentPage > 1) {
trialCurrentPage--;
applyTrialFiltersAndSort();
}
});
document.getElementById('trialNextPage')?.addEventListener('click', () => {
if (trialCurrentPage < trialTotalPages) {
trialCurrentPage++;
applyTrialFiltersAndSort();
}
});
document.getElementById('trialLastPage')?.addEventListener('click', () => {
trialCurrentPage = trialTotalPages;
applyTrialFiltersAndSort();
});
document.getElementById('trialPageSizeSelect')?.addEventListener('change', function () {
trialPageSize = parseInt(this.value);
trialCurrentPage = 1;
applyTrialFiltersAndSort();
});
// Filter and sort event listeners
document.getElementById('trialStartDateFilter')?.addEventListener('change', function () {
trialStartDateFilter = this.value;
trialCurrentPage = 1;
applyTrialFiltersAndSort();
});
document.getElementById('trialEndDateFilter')?.addEventListener('change', function () {
trialEndDateFilter = this.value;
trialCurrentPage = 1;
applyTrialFiltersAndSort();
});
document.getElementById('trialSortOrder')?.addEventListener('change', function () {
trialSortOrder = this.value;
trialCurrentPage = 1;
applyTrialFiltersAndSort();
});
// Intended product checkbox change handlers
setupIntendedProductCheckboxes('trialIntendedProductOtherCheckbox', 'trialIntendedProductOther');
setupIntendedProductCheckboxes('editTrialIntendedProductOtherCheckbox', 'editTrialIntendedProductOther');
// 为编辑弹窗的意向产品复选框添加监听器,控制时间字段显示
const editIntendedProductCheckboxes = document.querySelectorAll('input[name="editIntendedProduct"]');
editIntendedProductCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function () {
updateEditTrialTimeFieldsVisibility();
});
});
// 刷新按钮事件
const refreshTrialPeriodsBtn = document.getElementById('refreshTrialPeriodsBtn');
if (refreshTrialPeriodsBtn) {
refreshTrialPeriodsBtn.addEventListener('click', async function () {
// 添加旋转动画
refreshTrialPeriodsBtn.classList.add('refreshing');
const table = document.querySelector('.trial-periods-container table');
try {
await loadAllTrialPeriods();
// 成功反馈
refreshTrialPeriodsBtn.classList.remove('refreshing');
refreshTrialPeriodsBtn.classList.add('refresh-success');
// 添加表格刷新动画
if (table) {
table.classList.add('table-refreshing');
setTimeout(() => {
table.classList.remove('table-refreshing');
}, 500);
}
setTimeout(() => {
refreshTrialPeriodsBtn.classList.remove('refresh-success');
}, 1000);
} catch (error) {
refreshTrialPeriodsBtn.classList.remove('refreshing');
console.error('刷新失败:', error);
}
});
}
// Setup trial time visibility based on intended product selection
setupTrialTimeVisibility();
// Load customers map for displaying customer names
loadCustomersMap();
}
// Load customers map for displaying customer names in table
async function loadCustomersMap() {
try {
const response = await authenticatedFetch('/api/customers/list');
if (!response) {
console.error('No response from API');
return;
}
const data = await response.json();
// Use the complete customer map for ID->Name lookups
customersMap = data.customerMap || {};
// Also populate the customer select dropdown
populateCustomerSelect();
} catch (error) {
console.error('Error loading customers map:', error);
}
}
// Populate the customer select dropdown
function populateCustomerSelect() {
const select = document.getElementById('trialCustomerSelect');
if (!select) return;
select.innerHTML = '<option value="" disabled selected hidden>-- 选择已有客户或输入新客户 --</option>';
// Get unique names from customersMap
const names = [...new Set(Object.values(customersMap))].sort();
names.forEach(name => {
const option = document.createElement('option');
option.value = name;
option.textContent = name;
select.appendChild(option);
});
}
// Helper function to get customer name - returns friendly placeholder if not found
function getCustomerName(customerId) {
if (!customerId) return '未知客户';
const name = customersMap[customerId];
if (name) return name;
// If ID not found in map, return shortened ID with indicator
return '(已删除客户)';
}
// Alias for loadCustomersMap - used by main.js when switching to trial periods section
async function loadCustomersForDropdown() {
return await loadCustomersMap();
}
// Setup intended product checkboxes with "other" option handling
function setupIntendedProductCheckboxes(otherCheckboxId, otherInputId) {
const otherCheckbox = document.getElementById(otherCheckboxId);
const otherInput = document.getElementById(otherInputId);
if (!otherCheckbox || !otherInput) return;
otherCheckbox.addEventListener('change', function () {
if (this.checked) {
otherInput.style.display = 'block';
otherInput.focus();
} else {
otherInput.style.display = 'none';
otherInput.value = '';
}
});
}
// Setup trial time visibility based on intended product selection
// When only "robogo" or "其他" is selected (no "数据闭环"), hide start/end time fields
function setupTrialTimeVisibility() {
const checkboxGroup = document.getElementById('trialIntendedProductGroup');
if (!checkboxGroup) return;
const checkboxes = checkboxGroup.querySelectorAll('input[type="checkbox"]');
const startTimeGroup = document.getElementById('trialStartTimeGroup');
const endTimeGroup = document.getElementById('trialEndTimeGroup');
const isTrialGroup = document.getElementById('trialIsTrialGroup');
if (!startTimeGroup || !endTimeGroup || !isTrialGroup) return;
function updateTimeVisibility() {
const checkedBoxes = checkboxGroup.querySelectorAll('input[type="checkbox"]:checked');
const checkedValues = Array.from(checkedBoxes).map(cb => cb.value);
// Show time fields only if "数据闭环" is selected
const showTimeFields = checkedValues.includes('数据闭环');
startTimeGroup.style.display = showTimeFields ? 'block' : 'none';
endTimeGroup.style.display = showTimeFields ? 'block' : 'none';
isTrialGroup.style.display = showTimeFields ? 'block' : 'none';
}
// Add change listener to all checkboxes
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateTimeVisibility);
});
// Initial visibility check
updateTimeVisibility();
}
// Get intended product values from checkboxes (returns comma-separated string)
function getIntendedProductValues(checkboxName, otherInputId) {
const checkboxes = document.querySelectorAll(`input[name="${checkboxName}"]:checked`);
const otherInput = document.getElementById(otherInputId);
const values = [];
checkboxes.forEach(cb => {
if (cb.value === '其他') {
// If "other" is checked, use the custom input value
if (otherInput && otherInput.value.trim()) {
values.push(otherInput.value.trim());
}
} else {
values.push(cb.value);
}
});
return values.join(', ');
}
// Set intended product values in checkboxes (accepts comma-separated string)
function setIntendedProductValues(checkboxName, otherInputId, value) {
const checkboxes = document.querySelectorAll(`input[name="${checkboxName}"]`);
const otherInput = document.getElementById(otherInputId);
// Reset all checkboxes
checkboxes.forEach(cb => {
cb.checked = false;
});
if (otherInput) {
otherInput.style.display = 'none';
otherInput.value = '';
}
if (!value) return;
// Parse comma-separated values
const selectedValues = value.split(',').map(v => v.trim()).filter(v => v);
const predefinedOptions = ['数据闭环', 'robogo'];
let hasOther = false;
const otherValues = [];
selectedValues.forEach(val => {
if (predefinedOptions.includes(val)) {
// Check the corresponding checkbox
checkboxes.forEach(cb => {
if (cb.value === val) {
cb.checked = true;
}
});
} else {
// Custom value - mark as "other"
hasOther = true;
otherValues.push(val);
}
});
// Handle "other" checkbox and input
if (hasOther) {
checkboxes.forEach(cb => {
if (cb.value === '其他') {
cb.checked = true;
}
});
if (otherInput) {
otherInput.style.display = 'block';
otherInput.value = otherValues.join(', ');
}
}
}
// Legacy compatibility functions (for backward compatibility)
function setupIntendedProductDropdown(selectId, otherId) {
// No-op for backward compatibility - now using checkbox groups
}
function getIntendedProductValue(selectId, otherId) {
// Map to new checkbox-based function based on the select ID
if (selectId === 'trialIntendedProduct') {
return getIntendedProductValues('intendedProduct', 'trialIntendedProductOther');
} else if (selectId === 'editTrialIntendedProduct') {
return getIntendedProductValues('editIntendedProduct', 'editTrialIntendedProductOther');
}
return '';
}
function setIntendedProductValue(selectId, otherId, value) {
// Map to new checkbox-based function based on the select ID
if (selectId === 'trialIntendedProduct') {
setIntendedProductValues('intendedProduct', 'trialIntendedProductOther', value);
} else if (selectId === 'editTrialIntendedProduct') {
setIntendedProductValues('editIntendedProduct', 'editTrialIntendedProductOther', value);
}
}
// Load all trial periods
async function loadAllTrialPeriods() {
try {
const response = await authenticatedFetch('/api/trial-periods/all');
const data = await response.json();
trialPeriodsData = data.trialPeriods || [];
applyTrialFiltersAndSort();
renderExpiryWarnings();
} catch (error) {
console.error('Error loading trial periods:', error);
trialPeriodsData = [];
filteredTrialPeriodsData = [];
renderTrialPeriodsTable();
}
}
// Apply filters and sorting to trial periods
function applyTrialFiltersAndSort() {
let filtered = [...trialPeriodsData];
// Apply date range filter
if (trialStartDateFilter) {
filtered = filtered.filter(period => {
const endDate = new Date(period.endTime).toISOString().split('T')[0];
return endDate >= trialStartDateFilter;
});
}
if (trialEndDateFilter) {
filtered = filtered.filter(period => {
const endDate = new Date(period.endTime).toISOString().split('T')[0];
return endDate <= trialEndDateFilter;
});
}
// Sorting logic
filtered.sort((a, b) => {
if (trialSortOrder === 'createdAtDesc') {
const dateA = new Date(a.createdAt || 0);
const dateB = new Date(b.createdAt || 0);
return dateB - dateA; // Default: Created time descending
} else if (trialSortOrder === 'endTimeDesc') {
const dateA = new Date(a.endTime || 0);
const dateB = new Date(b.endTime || 0);
return dateB - dateA; // End time descending
}
return 0;
});
filteredTrialPeriodsData = filtered;
trialTotalItems = filteredTrialPeriodsData.length;
trialTotalPages = Math.ceil(trialTotalItems / trialPageSize);
renderTrialPeriodsTable();
updateTrialPagination();
}
// 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));
// 直接使用 customerName 字段
const customerName = period.customerName || '未知客户';
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 (filteredTrialPeriodsData.length === 0) {
const row = document.createElement('tr');
row.innerHTML = `
<td colspan="8" class="empty-state">
<i class="fas fa-users"></i>
<h3>👥 还没有客户试用信息</h3>
<p>点击上方「添加客户」开始管理客户试用</p>
</td>
`;
tbody.appendChild(row);
return;
}
// Paginate data
const startIndex = (trialCurrentPage - 1) * trialPageSize;
const endIndex = Math.min(startIndex + trialPageSize, filteredTrialPeriodsData.length);
const pageData = filteredTrialPeriodsData.slice(startIndex, endIndex);
pageData.forEach(period => {
const row = document.createElement('tr');
row.classList.add('trial-row');
// 直接使用 customerName 字段
const customerName = period.customerName || '未知客户';
// 计算状态和到期天数(使用日期比较,忽略具体时间)
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); // 今天 00:00:00
const endDate = new Date(period.endTime);
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()); // 结束日期 00:00:00
const startDate = new Date(period.startTime);
const daysUntilExpiry = Math.round((endDateOnly - today) / (1000 * 60 * 60 * 24));
const isTrial = (period.isTrial !== undefined && period.isTrial !== null) ? period.isTrial : false;
// 生成状态badge
let statusBadge = '';
if (!isTrial) {
statusBadge = '<span class="status-badge status-inactive"><i class="fas fa-pause-circle"></i> 非试用</span>';
} else if (daysUntilExpiry < 0) {
statusBadge = '<span class="status-badge status-expired"><i class="fas fa-times-circle"></i> 已到期</span>';
} else if (daysUntilExpiry === 0) {
statusBadge = '<span class="status-badge status-urgent"><i class="fas fa-exclamation-circle"></i> 今日到期</span>';
} else if (daysUntilExpiry <= 3) {
statusBadge = `<span class="status-badge status-warning"><i class="fas fa-clock"></i> ${daysUntilExpiry}天后到期</span>`;
} else if (daysUntilExpiry <= 7) {
statusBadge = `<span class="status-badge status-notice"><i class="fas fa-bell"></i> ${daysUntilExpiry}天后到期</span>`;
} else {
statusBadge = '<span class="status-badge status-active"><i class="fas fa-check-circle"></i> 试用中</span>';
}
const startTime = formatDateTime(period.startTime);
const endTime = formatDateTime(period.endTime);
const createdAt = formatDateTime(period.createdAt);
const source = period.source || '';
const intendedProduct = period.intendedProduct || '';
// 检查意向产品是否包含"数据闭环"
// 如果只包含 robogo 或其他,则不显示试用相关信息
const hasDataLoop = intendedProduct.includes('数据闭环');
// 根据是否有数据闭环来决定显示内容
const statusCell = hasDataLoop ? statusBadge : '<span style="color: #999;">-</span>';
const startTimeCell = hasDataLoop ? startTime : '<span style="color: #999;">-</span>';
const endTimeCell = hasDataLoop ? endTime : '<span style="color: #999;">-</span>';
// 生成意向产品标签
const productBadges = (period.intendedProduct || '').split(',')
.map(p => p.trim())
.filter(p => p)
.map(p => {
let colorClass = '';
if (p.includes('数据闭环')) {
colorClass = ''; // 保持默认绿色
} else if (p.toLowerCase().includes('robogo')) {
colorClass = 'product-badge-blue';
} else if (p.includes('数据生成')) {
colorClass = 'product-badge-orange';
} else {
colorClass = 'product-badge-purple'; // 其他类型用紫色
}
return `<span class="product-badge ${colorClass}">${p}</span>`;
}).join('');
// 生成跟进状态标签
const dealStatus = period.dealStatus || '初步接触';
let dealStatusBadge = '';
if (dealStatus === '已成交') {
dealStatusBadge = '<span class="deal-badge deal-closed-won"><i class="fas fa-trophy"></i> 已成交</span>';
} else if (dealStatus === '需求确认') {
dealStatusBadge = '<span class="deal-badge deal-trial"><i class="fas fa-clipboard-check"></i> 需求确认</span>';
} else if (dealStatus === '商务洽谈') {
dealStatusBadge = '<span class="deal-badge deal-negotiation"><i class="fas fa-handshake"></i> 商务洽谈</span>';
} else if (dealStatus === '已流失') {
dealStatusBadge = '<span class="deal-badge deal-lost"><i class="fas fa-times-circle"></i> 已流失</span>';
} else {
dealStatusBadge = '<span class="deal-badge deal-prospect"><i class="fas fa-user-clock"></i> 初步接触</span>';
}
row.innerHTML = `
<td><strong>${customerName}</strong></td>
<td>${source}</td>
<td>${productBadges}</td>
<td>${dealStatusBadge}</td>
<td>${statusCell}</td>
<td>${startTimeCell}</td>
<td>${endTimeCell}</td>
<td>${createdAt}</td>
<td class="action-cell">
<button class="action-btn edit-btn" data-id="${period.id}" title="编辑">
<i class="fas fa-edit"></i>
</button>
<button class="action-btn delete-btn ${!canDelete() ? 'disabled' : ''}" data-id="${period.id}" title="${!canDelete() ? '无删除权限' : '删除'}" ${!canDelete() ? 'disabled' : ''}>
<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:not(.disabled)').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;
applyTrialFiltersAndSort();
});
pageNumbers.appendChild(pageBtn);
}
}
// Open add trial modal
function openAddTrialModal() {
const inputEl = document.getElementById('trialCustomerInput');
if (inputEl) inputEl.value = '';
const sourceEl = document.getElementById('trialCustomerSource');
if (sourceEl) sourceEl.value = '';
// Reset intended product
setIntendedProductValue('trialIntendedProduct', 'trialIntendedProductOther', '');
// Reset deal status
const dealStatusEl = document.getElementById('trialDealStatus');
if (dealStatusEl) dealStatusEl.value = '初步接触';
document.querySelector('input[name="isTrial"][value="true"]').checked = true;
document.getElementById('trialStartTime').value = '';
document.getElementById('trialEndTime').value = '';
document.getElementById('addTrialPeriodModal').style.display = 'block';
}
// Open edit trial modal
function openEditTrialModal(periodId) {
const period = filteredTrialPeriodsData.find(p => p.id === periodId);
if (!period) return;
document.getElementById('editTrialPeriodId').value = period.id;
// Set customer source
const sourceEl = document.getElementById('editTrialCustomerSource');
if (sourceEl) sourceEl.value = period.source || '';
// Set intended product
setIntendedProductValue('editTrialIntendedProduct', 'editTrialIntendedProductOther', period.intendedProduct || '');
// Set deal status
const dealStatusEl = document.getElementById('editTrialDealStatus');
if (dealStatusEl) dealStatusEl.value = period.dealStatus || '初步接触';
const startDate = new Date(period.startTime);
const endDate = new Date(period.endTime);
document.getElementById('editTrialStartTime').value = formatDateTimeLocal(startDate);
document.getElementById('editTrialEndTime').value = formatDateTimeLocal(endDate);
// Set isTrial radio button
const isTrial = (period.isTrial !== undefined && period.isTrial !== null) ? period.isTrial : true;
const isTrialRadio = document.querySelector(`input[name="editIsTrial"][value="${isTrial}"]`);
if (isTrialRadio) {
isTrialRadio.checked = true;
}
// 控制时间字段的显示/隐藏
updateEditTrialTimeFieldsVisibility();
document.getElementById('editTrialPeriodModal').style.display = 'block';
}
// 更新编辑弹窗中时间字段的显示状态
function updateEditTrialTimeFieldsVisibility() {
const intendedProduct = getIntendedProductValue('editTrialIntendedProduct', 'editTrialIntendedProductOther');
const hasDataLoop = intendedProduct.includes('数据闭环');
const startTimeGroup = document.getElementById('editTrialStartTimeGroup');
const endTimeGroup = document.getElementById('editTrialEndTimeGroup');
const isTrialGroup = document.getElementById('editTrialIsTrialGroup');
if (startTimeGroup && endTimeGroup && isTrialGroup) {
if (hasDataLoop) {
startTimeGroup.style.display = 'block';
endTimeGroup.style.display = 'block';
isTrialGroup.style.display = 'block';
} else {
startTimeGroup.style.display = 'none';
endTimeGroup.style.display = 'none';
isTrialGroup.style.display = 'none';
}
}
}
// 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();
} else {
alert('删除试用时间时出错');
}
} catch (error) {
console.error('Error deleting trial period:', error);
alert('删除试用时间时出错');
}
}
// Create trial period from page
async function createTrialPeriodFromPage() {
const inputEl = document.getElementById('trialCustomerInput');
const sourceEl = document.getElementById('trialCustomerSource');
// Get customer name from input
const customerName = inputEl ? inputEl.value.trim() : '';
// Get customer source from input
const source = sourceEl ? sourceEl.value.trim() : '';
// Get intended product
const intendedProduct = getIntendedProductValue('trialIntendedProduct', 'trialIntendedProductOther');
const isTrialValue = document.querySelector('input[name="isTrial"]:checked').value;
const isTrial = isTrialValue === 'true';
const startTime = document.getElementById('trialStartTime').value;
const endTime = document.getElementById('trialEndTime').value;
const dealStatus = document.getElementById('trialDealStatus').value;
if (!customerName) {
alert('请选择或输入客户名称');
return;
}
// Only require start/end time if "数据闭环" is selected
const requiresTimeFields = intendedProduct.includes('数据闭环');
if (requiresTimeFields && (!startTime || !endTime)) {
alert('请填写开始时间和结束时间');
return;
}
// 直接使用 customerName不再需要查找或创建 customerId
const formData = {
customerName: customerName,
source: source,
intendedProduct: intendedProduct,
dealStatus: dealStatus,
startTime: startTime ? new Date(startTime).toISOString() : '',
endTime: endTime ? new Date(endTime).toISOString() : '',
isTrial: isTrial
};
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();
} else {
const errorText = await response.text();
alert(errorText || '添加试用时间时出错');
}
} 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();
});
}
});