feat:新增意向产品,去掉试用时间
This commit is contained in:
parent
df1be594ca
commit
db7646dbb1
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
2222
frontend/index.html
2222
frontend/index.html
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
|
||||
@ -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{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user