feat:新增意向产品,去掉试用时间

This commit is contained in:
hangyu.tao 2026-01-29 15:42:55 +08:00
parent df1be594ca
commit db7646dbb1
5 changed files with 925 additions and 1398 deletions

View File

@ -36,7 +36,7 @@ body {
/* Sidebar Styles */
.sidebar {
width: var(--sidebar-width);
background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
color: var(--white);
position: fixed;
height: 100vh;
@ -214,7 +214,7 @@ body {
transition: margin-left 0.3s ease;
}
.sidebar.collapsed ~ .main-content {
.sidebar.collapsed~.main-content {
margin-left: 70px;
}
@ -649,7 +649,7 @@ body {
cursor: pointer;
}
.checkbox-label input[type="checkbox"]:checked + span {
.checkbox-label input[type="checkbox"]:checked+span {
color: var(--primary-orange);
font-weight: 500;
}
@ -1104,7 +1104,7 @@ td.overflow-cell {
flex-direction: column;
}
.sidebar.collapsed ~ .main-content #editModal .modal-content {
.sidebar.collapsed~.main-content #editModal .modal-content {
width: min(calc(100vw - 70px - 80px), 800px);
}
@ -1126,7 +1126,7 @@ td.overflow-cell {
flex-direction: column;
}
.sidebar.collapsed ~ .main-content #createModal .modal-content {
.sidebar.collapsed~.main-content #createModal .modal-content {
width: min(calc(100vw - 70px - 80px), 800px);
}
@ -1559,6 +1559,7 @@ td.overflow-cell {
}
@keyframes pulse {
0%,
100% {
opacity: 1;
@ -2323,11 +2324,9 @@ tr:hover .action-cell {
}
.customer-tab.active {
background: linear-gradient(
135deg,
var(--primary-orange),
var(--secondary-orange)
);
background: linear-gradient(135deg,
var(--primary-orange),
var(--secondary-orange));
color: var(--white);
border-color: transparent;
box-shadow: 0 4px 12px rgba(255, 107, 53, 0.3);
@ -2696,4 +2695,4 @@ tr:hover .action-cell {
gap: 8px;
min-width: auto;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -191,9 +191,9 @@ document.addEventListener("DOMContentLoaded", function () {
placement === "top"
? rect.top - tipHeight - offset
: Math.min(
rect.bottom + offset,
window.innerHeight - viewportPadding - tipHeight,
);
rect.bottom + offset,
window.innerHeight - viewportPadding - tipHeight,
);
cellTooltipEl.style.left = `${Math.round(left)}px`;
cellTooltipEl.style.top = `${Math.round(top)}px`;
@ -1410,7 +1410,7 @@ document.addEventListener("DOMContentLoaded", function () {
const ctx = document.getElementById("statusChart").getContext("2d");
const selectedField = document.getElementById("chartFieldSelect").value;
const statusChartTitleEl = document.getElementById("statusChartTitle");
const chartTitle = statusChartTitleEl ? statusChartTitleEl.value : "数据分布";
const chartTitle = statusChartTitleEl ? statusChartTitleEl.value : "模块分布";
const fieldCount = {};
customers.forEach((customer) => {
@ -1518,7 +1518,7 @@ document.addEventListener("DOMContentLoaded", function () {
const ctx = canvas.getContext("2d");
const typeChartTitleEl = document.getElementById("typeChartTitle");
const chartTitle = typeChartTitleEl ? typeChartTitleEl.value : "客户类型";
const chartTitle = typeChartTitleEl ? typeChartTitleEl.value : "类型分布";
if (typeChartInstance) {
typeChartInstance.destroy();

View File

@ -83,7 +83,7 @@ function initTrialPeriodsPage() {
// 刷新按钮事件
const refreshTrialPeriodsBtn = document.getElementById('refreshTrialPeriodsBtn');
if (refreshTrialPeriodsBtn) {
refreshTrialPeriodsBtn.addEventListener('click', async function() {
refreshTrialPeriodsBtn.addEventListener('click', async function () {
// 添加旋转动画
refreshTrialPeriodsBtn.classList.add('refreshing');
const table = document.querySelector('.trial-periods-container table');
@ -109,6 +109,9 @@ function initTrialPeriodsPage() {
});
}
// Setup trial time visibility based on intended product selection
setupTrialTimeVisibility();
// Load customers map for displaying customer names
loadCustomersMap();
}
@ -184,6 +187,38 @@ function setupIntendedProductCheckboxes(otherCheckboxId, otherInputId) {
});
}
// 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');
if (!startTimeGroup || !endTimeGroup) 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';
}
// 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`);
@ -642,7 +677,9 @@ async function createTrialPeriodFromPage() {
return;
}
if (!startTime || !endTime) {
// Only require start/end time if "数据闭环" is selected
const requiresTimeFields = intendedProduct.includes('数据闭环');
if (requiresTimeFields && (!startTime || !endTime)) {
alert('请填写开始时间和结束时间');
return;
}
@ -652,8 +689,8 @@ async function createTrialPeriodFromPage() {
customerName: customerName,
source: source,
intendedProduct: intendedProduct,
startTime: new Date(startTime).toISOString(),
endTime: new Date(endTime).toISOString(),
startTime: startTime ? new Date(startTime).toISOString() : '',
endTime: endTime ? new Date(endTime).toISOString() : '',
isTrial: isTrial
};

View File

@ -69,17 +69,24 @@ func (h *TrialPeriodHandler) CreateTrialPeriod(w http.ResponseWriter, r *http.Re
return
}
// Parse start and end times
startTime, err := time.Parse(time.RFC3339, req.StartTime)
if err != nil {
http.Error(w, "Invalid start time format", http.StatusBadRequest)
return
// Parse start and end times (optional - only required for 数据闭环)
var startTime, endTime time.Time
var parseErr error
if req.StartTime != "" {
startTime, parseErr = time.Parse(time.RFC3339, req.StartTime)
if parseErr != nil {
http.Error(w, "Invalid start time format", http.StatusBadRequest)
return
}
}
endTime, err := time.Parse(time.RFC3339, req.EndTime)
if err != nil {
http.Error(w, "Invalid end time format", http.StatusBadRequest)
return
if req.EndTime != "" {
endTime, parseErr = time.Parse(time.RFC3339, req.EndTime)
if parseErr != nil {
http.Error(w, "Invalid end time format", http.StatusBadRequest)
return
}
}
trialPeriod := models.TrialPeriod{