PageSourceSearch

https://51paper.net/ai_mba_service/js/service_logic.js

js 51paper.net collected 2026-10-05 22:34:16 UTC 17,585 bytes, 313 lines download raw bytes

1$(document).ready(function() {
2    console.log("service_logic.js initialized.");
3
4    // --- 先声明所有可能用到的 jQuery 对象变量,初始值为 null ---
5    let $serviceSelectionForm = null;
6    let $homeServiceSelectionForm = null;
7    let $detailsFormSection = null;
8    let $detailsForm = null;
9    let $currentCheckboxes = null;
10    let $currentTotalPriceDisplay = null;
11    let $currentSubmitButton = null;
12    let $currentSelectionError = null;
13    // --- 服务页特定的元素,先声明 ---
14    let $detailsFormError = null;
15    let $loadingOverlay = null;
16    let $selectedServicesHidden = null;
17    let $totalAmountHidden = null;
18    let $backButton = null;
19
20    let isOnHomePage = false;
21    let isOnServicePage = false;
22
23    // --- 尝试获取页面元素来判断上下文 ---
24    $homeServiceSelectionForm = $('#service_selection_form_home'); // 首页的服务选择表单
25    $serviceSelectionForm = $('#service_selection_form');       // 服务页的服务选择表单
26    $detailsFormSection = $('#details_form_section');           // 详情表单区域
27    $detailsForm = $('#details_form');                       // 详情表单本身
28
29    // --- 根据元素存在情况确定上下文并初始化选择器 ---
30    if ($homeServiceSelectionForm.length > 0) {
31        // 当前在首页
32        isOnHomePage = true;
33        $currentCheckboxes = $homeServiceSelectionForm.find('input[name="services[]"]');
34        $currentTotalPriceDisplay = $homeServiceSelectionForm.find('#total_price_display'); // 假设 ID 在表单内部
35        $currentSubmitButton = $homeServiceSelectionForm.find('#submit_request_button_home');
36        $currentSelectionError = $homeServiceSelectionForm.find('#selection_error');
37        console.log("Context: Home Page");
38
39    } else if ($serviceSelectionForm.length > 0 || ($detailsFormSection.length > 0 && $detailsFormSection.is(':visible'))) { // 服务页判断条件优化
40        // 当前在服务页 (ai_mba_service/index.php)
41        isOnServicePage = true;
42        // 初始化服务页选择表单相关元素 (即使它可能在页面加载时隐藏)
43        if ($serviceSelectionForm.length > 0) {
44            $currentCheckboxes = $serviceSelectionForm.find('input[name="services[]"]');
45            $currentTotalPriceDisplay = $serviceSelectionForm.find('#total_price_display');
46            $currentSubmitButton = $serviceSelectionForm.find('#submit_request_button'); // 内部切换按钮
47            $currentSelectionError = $serviceSelectionForm.find('#selection_error');
48        } else {
49             // 如果服务选择表单不存在 (例如直接显示详情),将这些设为 null 或空 jQuery 对象
50             $currentCheckboxes = $(); // 空 jQuery 对象
51             $currentTotalPriceDisplay = $();
52             $currentSubmitButton = $(); // 这个按钮通常在服务选择表单内
53             $currentSelectionError = $();
54             console.log("Service selection form not found on service page (maybe showing details directly).");
55        }
56        // 初始化服务页详情表单相关元素 (这些元素应该总是存在于服务页面)
57        $detailsFormError = $('#form_error');
58        $loadingOverlay = $('#loading_overlay');
59        $selectedServicesHidden = $('#selected_services_json');
60        $totalAmountHidden = $('#total_amount_hidden');
61        $backButton = $('#back_to_selection');
62        console.log("Context: Service Page");
63
64    } else {
65        console.warn("service_logic.js: Could not determine page context (Home or Service). Script execution stopped.");
66        return; // 未知页面,退出
67    }
68
69    // --- 输出调试信息 ---
70    console.log("Checkboxes found:", ($currentCheckboxes ? $currentCheckboxes.length : 'N/A'));
71    console.log("Total Price Display found:", ($currentTotalPriceDisplay ? $currentTotalPriceDisplay.length : 'N/A'));
72    console.log("Submit Button found:", ($currentSubmitButton ? $currentSubmitButton.length : 'N/A'));
73    console.log("Selection Error found:", ($currentSelectionError ? $currentSelectionError.length : 'N/A'));
74    if(isOnServicePage){
75        console.log("Details Form Error found:", ($detailsFormError ? $detailsFormError.length : 'N/A'));
76        console.log("Loading Overlay found:", ($loadingOverlay ? $loadingOverlay.length : 'N/A'));
77        console.log("Selected Services Hidden found:", ($selectedServicesHidden ? $selectedServicesHidden.length : 'N/A'));
78        console.log("Total Amount Hidden found:", ($totalAmountHidden ? $totalAmountHidden.length : 'N/A'));
79        console.log("Back Button found:", ($backButton ? $backButton.length : 'N/A'));
80    }
81
82    // --- 核心计价与按钮状态更新函数 ---
83    function updatePriceAndButtonState() {
84        // console.log("updatePriceAndButtonState called.");
85        let total = 0;
86        let count = 0;
87        let selectedServices = [];
88
89        // 只有当复选框存在时才计算
90        if ($currentCheckboxes && $currentCheckboxes.length > 0) {
91            $currentCheckboxes.each(function() {
92                const $checkbox = $(this);
93                if ($checkbox.is(':checked')) {
94                    const price = parseFloat($checkbox.data('price'));
95                    if (!isNaN(price)) {
96                        total += price;
97                        count++;
98                        // 只在服务页需要构建详细的服务列表
99                        if (isOnServicePage) {
100                            let label = $checkbox.closest('tr').find('label strong').text();
101                            selectedServices.push({ id: $checkbox.val(), name: label, price: price.toFixed(2) });
102                        }
103                    } else { console.error("Invalid price data:", $checkbox.data('price'), "on checkbox:", $checkbox.val()); }
104                }
105            });
106        }
106 else if (isOnServicePage && $('body').hasClass('show-details-on-load')) {
107             // 如果服务页直接显示详情,从隐藏字段恢复数据 (确保隐藏字段变量已赋值)
108             if ($totalAmountHidden && $totalAmountHidden.length > 0) {
109                 const preTotal = parseFloat($totalAmountHidden.val());
110                 if (!isNaN(preTotal)) { total = preTotal; }
111             }
112             if ($selectedServicesHidden && $selectedServicesHidden.length > 0) {
113                 const preSelectedJson = $selectedServicesHidden.val();
114                 try {
115                     selectedServices = JSON.parse(preSelectedJson || '[]');
116                 } catch (e) { console.error("Error parsing pre-selected services JSON:", e); selectedServices = []; }
117                 count = selectedServices.length; // 更新 count
118             }
119             console.log("Using pre-filled data on service page load:", total, selectedServices);
120        }
121
122        // 更新价格显示 (确保元素存在)
123        if ($currentTotalPriceDisplay && $currentTotalPriceDisplay.length > 0) {
124            $currentTotalPriceDisplay.text(total.toFixed(2));
125        }
126
127        // 更新按钮状态 (确保按钮存在)
128        if ($currentSubmitButton && $currentSubmitButton.length > 0) {
129            $currentSubmitButton.prop('disabled', count <= 0);
130            // 处理错误提示显示/隐藏 (确保元素存在)
131            if ($currentSelectionError && $currentSelectionError.length > 0) {
132                if (count <= 0 && !isOnHomePage) { // 只在服务页计价为0时显示错误
133                    $currentSelectionError.slideDown();
134                } else {
135                    $currentSelectionError.slideUp();
136                }
137            }
138        }
139        return { total: total, count: count, selected: selectedServices }; // 返回 count
140    }
141
142    // --- 事件绑定 ---
143    // 1. 为复选框绑定 change 事件 (如果存在)
144    if ($currentCheckboxes && $currentCheckboxes.length > 0) {
145        $currentCheckboxes.on('change', updatePriceAndButtonState);
146        console.log("Checkbox 'change' event handler bound.");
147    }
148
149    // --- 页面加载时进行一次计算和状态更新 ---
150    updatePriceAndButtonState(); // 确保初始状态正确
151    console.log("Initial price and button state updated.");
152
153
154    // ===========================================================
155    // --- 仅在服务页 (ai_mba_service/index.php) 执行的逻辑 ---
156    // ===========================================================
157    if (isOnServicePage) {
158        console.log("Setting up Service Page specific logic.");
159
160        // 2. 服务页内部切换的 "下一步" 按钮点击事件 (确保按钮存在)
161        if ($currentSubmitButton && $currentSubmitButton.attr('id') === 'submit_request_button') {
162            $currentSubmitButton.off('click').on('click', function() {
163                console.log("Service Page internal 'Next' button clicked.");
164                let calculation = updatePriceAndButtonState(); // 获取最新选择
165                // 使用返回的 count 判断
166                if (calculation.count <= 0) {
167                    if ($currentSelectionError && $currentSelectionError.length > 0) $currentSelectionError.slideDown();
168                    return;
169                }
170                // 填充隐藏字段 (确保变量已定义且元素存在)
171                if($selectedServicesHidden && $selectedServicesHidden.length > 0) {
172                    $selectedServicesHidden.val(JSON.stringify(calculation.selected));
173                }
174                if($totalAmountHidden && $totalAmountHidden.length > 0) {
175                    $totalAmountHidden.val(calculation.total.toFixed(2));
176                }
177                // 执行切换 (确保变量已定义且元素存在)
178                const $serviceSection = $('#service_selection_section'); // 在函数内重新获取
179                if ($serviceSection.length > 0 && $detailsFormSection.length > 0) {
180                    $serviceSection.slideUp(400, function() {
181                        $detailsFormSection.slideDown(400);
182                        $('html, body').animate({ scrollTop: $detailsFormSection.offset().top - 100 }, 500);
183                    });
184                } else {
185                     console.error("Cannot toggle sections for 'Next' button, elements not found.");
186                }
187            });
188            console.log("Service Page internal 'Next' button click handler bound.");
189        } else if ($currentSubmitButton) {
190             console.log("Submit button found, but ID is not 'submit_request_button'.");
191        } else {
192             console.log("Service Page internal 'Next' button not found.");
193        }
194
195        // 3. "返回修改服务" 按钮点击事件 (确保变量已定义且元素存在)
196        if ($backButton && $backButton.length > 0) {
197            $backButton.off('click').on('click', function() {
198                console.log("Service Page 'Back' button clicked.");
199                 const $serviceSection = $('#service_selection_section'); // 重新获取
200                if ($detailsFormSection.length > 0 && $serviceSection.length > 0) {
201                    $detailsFormSection.slideUp(400, function() {
202                        $serviceSection.slideDown(400);
203                        // 可选滚动
204                        // $('html, body').animate({ scrollTop: $serviceSection.offset().top - 100 }, 500);
205                    });
206                } else {
207                     console.error("Cannot toggle sections for 'Back' button, elements not found.");
208                }
209            });
210            console.log("Service Page 'Back' button click handler bound.");
211        } else {
212             console.log("Service Page 'Back' button not found.");
213        }
214
215        // 4. 详情表单提交事件 (确保变量已定义且元素存在)
216        if ($detailsForm && $detailsForm.length > 0) {
217            $detailsForm.on('submit', function(e) {
218                console.log("Details form submit event triggered.");
219                // --- 前端验证 ---
220                let isValid = true;
221                let errorMessages = [];
222                if($detailsFormError && $detailsFormError.length > 0) $detailsFormError.hide().empty(); // 确保错误提示元素存在
223
224                let title = $('#thesis_title').val().trim();
225                let requirements = $('#requirements').val().trim();
226
227                if (!title) { isValid = false; errorMessages.push('请填写论文题目或研究方向。'); $('#thesis_title').addClass('is-invalid'); } else { $('#thesis_title').removeClass('is-invalid'); }
228                if (!requirements) { isValid = false; errorMessages.push('请填写详细要求。'); $('#requirements').addClass('is-invalid'); } else { $('#requirements').removeClass('is-invalid'); }
229
230                // 文件大小验证
231                 let fileInput = $('#attachment')[0];
232                 if (fileInput && fileInput.files.length > 0) {
233                    let file = fileInput.files[0]; let maxSize = 10 * 1024 * 1024;
234                    if (file.size > maxSize) { isValid = false; errorMessages.push('上传的文件不能超过 10MB。'); $('#attachment').addClass('is-invalid'); } else { $('#attachment').removeClass('is-invalid'); }
235                 } else { $('#attachment').removeClass('is-invalid'); }
236
237
238                if (!isValid) {
239                    e.preventDefault(); // 阻止提交
240                    let errorHtml = '<ul>'; errorMessages.forEach(msg => { errorHtml += '<li>' + msg + '</li>'; }); errorHtml += '</ul>';
241                    if($detailsFormError && $detailsFormError.length > 0) {
242                        $detailsFormError.html(errorHtml).slideDown();
243                        // 滚动到错误位置
244                        $('html, body').animate({ scrollTop: $detailsFormError.offset().top - 150 }, 300);
245                    } else {
246                         alert(errorMessages.join("\n")); // 后备 alert
247                    }
248                    return false;
249                }
250
251                // 验证通过,显示加载动画 (确保元素存在)
252                if ($loadingOverlay && $loadingOverlay.length > 0) $loadingOverlay.fadeIn();
253                else console.log("Loading overlay not found.");
254            });
255
256             // 输入时移除错误样式逻辑
257             $('#thesis_title, #requirements').on('input', function() { $(this).removeClass('is-invalid'); });
258             $('#attachment').on('change', function() { $(this).removeClass('is-invalid'); /* 可添加更详细的文件验证 */ });
259             console.log("Details form submit handler bound.");
260        } else {
261             console.log("Details form (#details_form) not found.");
262        }
263
264
265        // 5. 页面加载时检查是否直接显示详情
266        if ($('body').hasClass('show-details-on-load')) {
267            console.log("Service Page: Detected 'show-details-on-load' class, adjusting view.");
268            const $serviceSection = $('#service_selection_section'); // 重新获取
269            if($serviceSection.length > 0) $serviceSection.hide();
270            if($detailsFormSection.length > 0) {
271                 // 确保在显示后进行滚动
272                 if ($detailsFormSection.is(':hidden')) {
273                     $detailsFormSection.show();
274                 }
275                 // 延迟滚动
276                 setTimeout(function() {
277                     if ($detailsFormSection.is(':visible')) { // 再次确认可见
278                        $('html, body').animate({ scrollTop: $detailsFormSection.offset().top - 100 }, 500);
279                     }
280                 }, 100);
281            }
282        }
283
284    } else if (isOnHomePage) {
285        // --- 仅在首页执行的逻辑 ---
286        console.log("Running Home Page specific logic.");
287        // 首页表单提交验证 (防止未选服务时提交)
288         if ($homeServiceSelectionForm && $homeServiceSelectionForm.length > 0) {
289             $homeServiceSelectionForm.on('submit', function(e){
290                  let calculation = updatePriceAndButtonState(); // 获取最新状态
291                   if (calculation.count <= 0) { // 使用 count 判断
292                       e.preventDefault(); // 阻止提交
293                       if ($currentSelectionError && $currentSelectionError.length > 0) {
294                           $currentSelectionError.slideDown();
295                           // 添加震动效果 (需要 animate.css 或自定义动画)
296                           // $currentSelectionError.addClass('animate__animated animate__shakeX');
297                           // setTimeout(() => $currentSelectionError.removeClass('animate__animated animate__shakeX'), 800);
298                       }
299                       console.log("Home page form submission prevented: No services selected.");
300                       return false;
301                   }
302                   console.log("Home page form submitting...");
303                   // 允许提交到 /ai_mba_service/index.php
304             });
305             console.log("Home page form submit validation bound.");
306         } else {
307              console.warn("Home page form not found for submit binding.");
308         }
309
310    }
311
312    console.log("service_logic.js setup complete.");
313}); // <-- $(document).ready 结束

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.