市场夺宝奇兵
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

715 lines
31 KiB

2 days ago
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <meta http-equiv="pragma" content="no-cache">
  8. <meta http-equiv="cache-control" content="no-cache">
  9. <meta http-equiv="expires" content="0">
  10. <link rel="shortcut icon" href="dbqb_favicon.ico" />
  11. <link rel="Bookmark" href="dbqb_favicon.ico" />
  12. <meta http-equiv="keywords" content="夺宝奇兵,意见反馈,用户反馈">
  13. <meta http-equiv="description" content="夺宝奇兵用户意见反馈页面">
  14. <title>夺宝奇兵 - 意见反馈</title>
  15. <!-- 引入外部资源 -->
  16. <script src="https://cdn.tailwindcss.com?v=3.3.5"></script>
  17. <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  18. <!-- 基础样式配置 -->
  19. <script>
  20. tailwind.config = {
  21. theme: {
  22. extend: {
  23. colors: {
  24. primary: '#3B82F6',
  25. secondary: '#8B5CF6',
  26. danger: '#EF4444',
  27. success: '#10B981'
  28. }
  29. }
  30. }
  31. }
  32. </script>
  33. <style type="text/tailwindcss">
  34. @layer utilities {
  35. .input-focus {
  36. @apply focus:ring-2 focus:ring-primary/50 focus:border-primary focus:outline-none;
  37. }
  38. .input-error {
  39. @apply border-danger focus:ring-danger/20 focus:border-danger;
  40. }
  41. .btn-effect {
  42. @apply relative overflow-hidden transition-all duration-300;
  43. }
  44. .btn-effect::after {
  45. content: '';
  46. @apply absolute top-0 left-[-100%] w-full h-full bg-white/20 transform skew-x-12 transition-all duration-500;
  47. }
  48. .btn-effect:hover::after {
  49. @apply left-[100%];
  50. }
  51. .card-shadow {
  52. @apply shadow-md hover:shadow-lg transition-shadow duration-300;
  53. }
  54. .modal-backdrop {
  55. @apply fixed inset-0 bg-black/50 z-50 flex items-center justify-center opacity-0 pointer-events-none transition-opacity duration-300;
  56. }
  57. .modal-backdrop.active {
  58. @apply opacity-100 pointer-events-auto;
  59. }
  60. .modal-content {
  61. @apply bg-white rounded-xl shadow-2xl max-w-md w-full mx-4 transform translate-y-8 transition-transform duration-300;
  62. }
  63. .modal-backdrop.active .modal-content {
  64. @apply translate-y-0;
  65. }
  66. .error-message {
  67. @apply text-danger text-sm mt-1 hidden;
  68. }
  69. .country-select-container {
  70. @apply relative;
  71. }
  72. .country-select {
  73. @apply appearance-none bg-white border border-gray-300 rounded-lg py-3 pl-10 pr-10 input-focus transition-colors w-full;
  74. }
  75. .loading-spinner {
  76. @apply inline-block w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin;
  77. }
  78. }
  79. </style>
  80. <style>
  81. /* 确保基础样式生效 */
  82. body {
  83. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  84. }
  85. /* 简单动画 */
  86. @keyframes fadeIn {
  87. from {
  88. opacity: 0;
  89. transform: translateY(10px);
  90. }
  91. to {
  92. opacity: 1;
  93. transform: translateY(0);
  94. }
  95. }
  96. .fade-in {
  97. animation: fadeIn 0.5s ease-out forwards;
  98. }
  99. .delay-100 {
  100. animation-delay: 0.1s;
  101. }
  102. .delay-200 {
  103. animation-delay: 0.2s;
  104. }
  105. .delay-300 {
  106. animation-delay: 0.3s;
  107. }
  108. /* 国家选择框箭头样式 */
  109. .country-select-arrow {
  110. pointer-events: none;
  111. }
  112. /* 国家选择下拉列表样式 */
  113. .country-select option {
  114. padding: 8px 12px;
  115. }
  116. /* 确保3:7比例在所有中等及以上屏幕生效 */
  117. @media (min-width: 640px) {
  118. .whatsapp-container {
  119. display: flex;
  120. gap: 1rem;
  121. }
  122. .country-code-wrapper {
  123. width: 30%;
  124. }
  125. .phone-number-wrapper {
  126. width: 70%;
  127. }
  128. }
  129. </style>
  130. </head>
  131. <body class="bg-gray-50 text-gray-800">
  132. <!-- 导航栏 -->
  133. <header class="fixed top-0 left-0 right-0 bg-white/95 shadow-sm z-50">
  134. <div class="container mx-auto px-4 py-4 flex justify-between items-center">
  135. <div class="flex items-center space-x-2">
  136. <div
  137. class="w-10 h-10 rounded-lg bg-gradient-to-r from-primary to-secondary flex items-center justify-center">
  138. <img alt="夺宝奇兵" src="https://hc.homilychart.com/hc/250121/img/20230711171637.png"
  139. style="width: 40px;height: 40px;">
  140. </div>
  141. <span
  142. class="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-primary to-secondary">意见反馈</span>
  143. </div>
  144. <!-- 桌面导航 -->
  145. <nav class="hidden md:flex items-center space-x-8">
  146. <a href="./hkhcdbqb.html" class="hover:text-primary transition-colors">首页</a>
  147. <a href="#" class="text-primary font-medium">意见反馈</a>
  148. <a href="https://wa.me/85269518757?text=夺宝奇兵我需要帮助" target="_blank"
  149. class="px-5 py-2 rounded-full bg-gradient-to-r from-primary to-secondary text-white hover:shadow-lg transition-all">联系我们</a>
  150. </nav>
  151. <!-- 移动端菜单 -->
  152. <button id="mobileMenuBtn" class="md:hidden text-xl">
  153. <i class="fa fa-bars"></i>
  154. </button>
  155. </div>
  156. <!-- 移动端菜单内容 -->
  157. <div id="mobileMenu" class="md:hidden hidden bg-white border-t">
  158. <div class="container mx-auto px-4 py-3 flex flex-col space-y-3">
  159. <a href="#" class="py-2 hover:text-primary transition-colors">首页</a>
  160. <a href="#" class="py-2 text-primary">意见反馈</a>
  161. <a href="https://wa.me/85269518757?text=夺宝奇兵我需要帮助" target="_blank"
  162. class="py-2 mt-2 rounded-full bg-gradient-to-r from-primary to-secondary text-white text-center">联系我们</a>
  163. </div>
  164. </div>
  165. </header>
  166. <!-- 主要内容 -->
  167. <main class="pt-28 pb-16 px-4">
  168. <div class="container mx-auto max-w-4xl">
  169. <!-- 页面标题 -->
  170. <div class="text-center mb-12 fade-in">
  171. <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold mb-4">意见反馈</h1>
  172. <p class="text-gray-600 max-w-2xl mx-auto">感谢您对Adam说港股团队的支持!<br>请留下您的宝贵意见和建议,我们将不断的提升服务质量!</p>
  173. </div>
  174. <!-- 反馈表单卡片 -->
  175. <div class="bg-white rounded-xl p-6 md:p-8 mb-10 fade-in delay-100 card-shadow">
  176. <form id="feedbackForm" class="space-y-6">
  177. <!-- 姓名输入 -->
  178. <div class="form-group">
  179. <label for="name" class="block text-gray-700 font-medium mb-2">姓名 <span
  180. class="text-danger">*</span></label>
  181. <div class="relative">
  182. <div
  183. class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-gray-400">
  184. <i class="fa fa-user"></i>
  185. </div>
  186. <input type="text" id="fusername" name="fusername" required
  187. class="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg input-focus transition-colors"
  188. placeholder="请输入您的姓名">
  189. <div class="error-message" id="nameError">请输入您的姓名</div>
  190. </div>
  191. </div>
  192. <!-- WhatsApp号码 - 精确3:7比例布局 -->
  193. <div class="form-group">
  194. <label class="block text-gray-700 font-medium mb-2">Whatsapp <span
  195. class="text-danger">*</span></label>
  196. <div class="whatsapp-container flex flex-col sm:flex-row gap-3">
  197. <!-- 国家选择(30%宽度) -->
  198. <div class="country-code-wrapper country-select-container">
  199. <div
  200. class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-gray-400">
  201. <i class="fa fa-whatsapp"></i>
  202. </div>
  203. <select id="countryinfo" name="countryinfo" required class="country-select">
  204. <option value="+65">+65 新加坡</option>
  205. <option value="+60">+60 马来西亚</option>
  206. <option value="+852">+852 香港</option>
  207. <option value="+1" selected='selected'>+1 美国</option>
  208. <option value="+62">+62 印尼</option>
  209. <option value="+1">+1 加拿大</option>
  210. <option value="+61">+61 澳大利亚</option>
  211. <option value="+673">+673 文莱</option>
  212. <option value="+886">+886 台湾</option>
  213. <option value="+86">+86 中国</option>
  214. <option value="+0">+0 其他</option>
  215. <option value="+64">+64 新西兰</option>
  216. <option value="+44">+44 英国</option>
  217. <option value="+81">+81 日本</option>
  218. <option value="+49">+49 德国</option>
  219. <option value="+82">+82 韩国</option>
  220. <option value="+84 ">+84 越南</option>
  221. <option value="+971">+971 阿联酋</option>
  222. <option value="+45">+45 丹麦</option>
  223. <option value="+853">+853 澳门</option>
  224. <option value="+66">+66 泰国</option>
  225. <option value="+91">+91 印度</option>
  226. <option value="+41">+41 瑞士</option>
  227. <option value="+358">+358 芬兰</option>
  228. <option value="+33">+33 法国</option>
  229. <option value="+63">+63 菲律宾</option>
  230. <option value="+31">+31 荷兰</option>
  231. <option value="+46">+46 瑞典</option>
  232. <option value="+34">+34 西班牙</option>
  233. <option value="+54">+54 阿根廷</option>
  234. <option value="+39">+39 意大利</option>
  235. <option value="+7">+7 俄罗斯</option>
  236. <option value="+420">+420 捷克</option>
  237. </select>
  238. <div
  239. class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none text-gray-400 country-select-arrow">
  240. <i class="fa fa-chevron-down"></i>
  241. </div>
  242. <div class="error-message" id="countryCodeError">请选择国家/地区</div>
  243. </div>
  244. <!-- 手机号(70%宽度) -->
  245. <div class="phone-number-wrapper relative">
  246. <div
  247. class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-gray-400">
  248. <i class="fa fa-mobile text-lg"></i>
  249. </div>
  250. <input type="tel" id="umoblie" name="umoblie" required
  251. class="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg input-focus transition-colors"
  252. placeholder="请输入手机号码">
  253. <div class="error-message" id="phoneError">请输入有效的手机号码</div>
  254. </div>
  255. </div>
  256. </div>
  257. <!-- 微信ID输入 -->
  258. <div class="form-group">
  259. <label for="wechatId" class="block text-gray-700 font-medium mb-2">微信ID</label>
  260. <div class="relative">
  261. <div
  262. class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-gray-400">
  263. <i class="fa fa-weixin"></i>
  264. </div>
  265. <input type="text" id="fwechat" name="fwechat"
  266. class="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg input-focus transition-colors"
  267. placeholder="请输入您的微信ID(选填)">
  268. </div>
  269. </div>
  270. <!-- 邮箱输入 -->
  271. <div class="form-group">
  272. <label for="email" class="block text-gray-700 font-medium mb-2">邮箱 <span
  273. class="text-danger">*</span></label>
  274. <div class="relative">
  275. <div
  276. class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-gray-400">
  277. <i class="fa fa-envelope"></i>
  278. </div>
  279. <input type="email" id="femail" name="femail" required
  280. class="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg input-focus transition-colors"
  281. placeholder="请输入您的邮箱地址">
  282. <div class="error-message" id="emailError">请输入有效的邮箱地址</div>
  283. </div>
  284. </div>
  285. <!-- 反馈类型 -->
  286. <div class="form-group">
  287. <label for="feedbackType" class="block text-gray-700 font-medium mb-2">反馈类型</label>
  288. <div class="relative">
  289. <div
  290. class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-gray-400">
  291. <i class="fa fa-tag"></i>
  292. </div>
  293. <select id="ftype" name="ftype"
  294. class="w-full pl-10 pr-10 py-3 border border-gray-300 rounded-lg input-focus transition-colors appearance-none bg-white">
  295. <option value="功能建议">功能建议</option>
  296. <option value="问题反馈">问题反馈</option>
  297. <option value="体验优化">体验优化</option>
  298. <option value="其他建议">其他建议</option>
  299. </select>
  300. <div
  301. class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none text-gray-400">
  302. <i class="fa fa-chevron-down"></i>
  303. </div>
  304. </div>
  305. </div>
  306. <!-- 反馈内容(增加最大长度500字的实时限制与校验) -->
  307. <div class="form-group">
  308. <label for="feedbackContent" class="block text-gray-700 font-medium mb-2">反馈内容 <span
  309. class="text-danger">*</span></label>
  310. <div class="relative">
  311. <textarea id="fcontent" name="fcontent" rows="5" required maxlength="500"
  312. class="w-full px-4 py-3 border border-gray-300 rounded-lg input-focus transition-colors resize-none"
  313. placeholder="请详细描述您的意见或建议...(最多500字)"></textarea>
  314. <div class="absolute right-3 bottom-3 text-gray-400 text-sm">
  315. <span id="charCount">0</span> / 500
  316. </div>
  317. <div class="error-message" id="feedbackContentError">请输入反馈内容(至少10个字符,最多500字)</div>
  318. </div>
  319. </div>
  320. <!-- 提交按钮 -->
  321. <div class="pt-4">
  322. <button type="submit" id="submitBtn"
  323. class="btn-effect w-full py-3 px-6 rounded-lg bg-gradient-to-r from-primary to-secondary text-white font-medium text-lg flex items-center justify-center">
  324. <i class="fa fa-paper-plane mr-2"></i>
  325. <span>提交反馈</span>
  326. <span id="loadingIndicator" class="ml-2 hidden">
  327. <span class="loading-spinner"></span>
  328. </span>
  329. </button>
  330. </div>
  331. </form>
  332. </div>
  333. <!-- 反馈须知 -->
  334. <div
  335. class="bg-gradient-to-r from-primary/5 to-secondary/5 border border-primary/20 rounded-xl p-6 mb-16 fade-in delay-200">
  336. <h3 class="font-semibold text-lg text-gray-800 mb-4 flex items-center">
  337. <i class="fa fa-info-circle text-primary mr-2"></i>反馈须知
  338. </h3>
  339. <ul class="space-y-2 text-gray-700">
  340. <li class="flex items-start">
  341. <i class="fa fa-check-circle text-success mt-1 mr-2 flex-shrink-0"></i>
  342. <span>我们会在1-3个工作日内处理您的反馈并给予回复</span>
  343. </li>
  344. <li class="flex items-start">
  345. <i class="fa fa-check-circle text-success mt-1 mr-2 flex-shrink-0"></i>
  346. <span><span class="text-danger">*</span> 的为必填项,请确保信息准确无误</span>
  347. </li>
  348. <li class="flex items-start">
  349. <i class="fa fa-check-circle text-success mt-1 mr-2 flex-shrink-0"></i>
  350. <span>您的个人信息仅用于反馈跟进,我们将严格保密</span>
  351. </li>
  352. <li class="flex items-start">
  353. <i class="fa fa-check-circle text-success mt-1 mr-2 flex-shrink-0"></i>
  354. <span>反馈内容限500字以内,请合理控制字数</span>
  355. </li>
  356. </ul>
  357. </div>
  358. </div>
  359. </main>
  360. <!-- 成功弹窗(与参考页面样式一致,点击确定按钮关闭) -->
  361. <div id="successModal" class="modal-backdrop" role="dialog" aria-modal="true">
  362. <div class="modal-content p-6">
  363. <div class="text-center">
  364. <div class="w-16 h-16 rounded-full bg-success/20 flex items-center justify-center mx-auto mb-4">
  365. <i class="fa fa-check-circle text-success text-3xl"></i>
  366. </div>
  367. <h3 class="text-xl font-bold mb-2">反馈成功!</h3>
  368. <p class="text-gray-600 mb-6">感谢您的反馈,我们将持续优化更新</p>
  369. <button id="closeModalBtn"
  370. class="px-6 py-2 bg-gradient-to-r from-primary to-secondary text-white rounded-lg hover:shadow-lg transition-all">
  371. 确定
  372. </button>
  373. </div>
  374. </div>
  375. </div>
  376. <!-- 页脚 -->
  377. <footer class="bg-gray-900 text-white py-10 px-4">
  378. <div class="container mx-auto max-w-6xl text-center">
  379. <div class="mb-6">
  380. <div class="inline-flex items-center space-x-2">
  381. <div class="w-10 h-10 rounded-lg gradient-bg flex items-center justify-center">
  382. <img alt="夺宝奇兵" src="https://hc.homilychart.com/hc/250121/img/20230711171637.png
  383. " style="width: 40px;height: 40px;">
  384. </div>
  385. <span class="font-bold">夺宝奇兵</span>
  386. </div>
  387. </div>
  388. <p class="text-gray-400 text-sm mb-4">Copyright 2026.Capitalmaster Pte Ltd All Rights Reserved.</p>
  389. </div>
  390. </footer>
  391. <script type="module">
  392. // 从外部文件导入 registerMemberApi 函数
  393. import { registerMemberApi } from './src/api/hkmember.js';
  394. // DOM 元素
  395. const form = document.getElementById('feedbackForm');
  396. const submitBtn = document.getElementById('submitBtn');
  397. const loadingIndicator = document.getElementById('loadingIndicator');
  398. const successModal = document.getElementById('successModal');
  399. const closeModalBtn = document.getElementById('closeModalBtn');
  400. // 字符计数
  401. const fcontent = document.getElementById('fcontent');
  402. const charCount = document.getElementById('charCount');
  403. // 错误提示元素
  404. const nameError = document.getElementById('nameError');
  405. const phoneError = document.getElementById('phoneError');
  406. const emailError = document.getElementById('emailError');
  407. const feedbackContentError = document.getElementById('feedbackContentError');
  408. // 隐藏所有错误提示
  409. function hideAllErrors() {
  410. nameError.style.display = 'none';
  411. phoneError.style.display = 'none';
  412. emailError.style.display = 'none';
  413. feedbackContentError.style.display = 'none';
  414. }
  415. // 显示错误提示
  416. function showError(element, message) {
  417. if (element) {
  418. element.textContent = message;
  419. element.style.display = 'block';
  420. }
  421. }
  422. // 显示成功弹窗
  423. function showSuccessModal() {
  424. successModal.classList.add('active');
  425. }
  426. // 隐藏成功弹窗
  427. function hideSuccessModal() {
  428. successModal.classList.remove('active');
  429. }
  430. // 关闭弹窗事件
  431. closeModalBtn.addEventListener('click', hideSuccessModal);
  432. // 点击模态框背景关闭
  433. successModal.addEventListener('click', function (e) {
  434. if (e.target === successModal) {
  435. hideSuccessModal();
  436. }
  437. });
  438. // 邮箱校验
  439. function isValidEmail(email) {
  440. const emailRegex = /^[^\s@]+@([^\s@]+\.)+[^\s@]+$/;
  441. if (!emailRegex.test(email)) return false;
  442. if (email.length > 254) return false;
  443. if (email.includes('..')) return false;
  444. return true;
  445. }
  446. // 手机号校验
  447. function isValidPhone(phone) {
  448. if (!phone || phone.trim() === '') return false;
  449. const digitsOnly = phone.replace(/[^\d]/g, '');
  450. if (digitsOnly.length < 4 || digitsOnly.length > 20) return false;
  451. return true;
  452. }
  453. // 清理手机号
  454. function cleanPhoneNumber(phone) {
  455. if (!phone) return '';
  456. let cleaned = phone.replace(/[^\d]/g, '');
  457. cleaned = cleaned.replace(/^(00)/, '');
  458. return cleaned;
  459. }
  460. // 反馈类型映射
  461. function getFeedbackTypeValue(typeText) {
  462. const typeMap = {
  463. '功能建议': '1',
  464. '问题反馈': '2',
  465. '体验优化': '3',
  466. '其他建议': '4'
  467. };
  468. return typeMap[typeText] || '4';
  469. }
  470. // 字符计数 & 实时限制(确保不超过500字,与maxlength配合)
  471. if (fcontent && charCount) {
  472. // 初始化显示
  473. charCount.textContent = fcontent.value.length;
  474. fcontent.addEventListener('input', function () {
  475. let len = this.value.length;
  476. // 双重保险:如果超过500则截断
  477. if (len > 500) {
  478. this.value = this.value.substring(0, 500);
  479. len = 500;
  480. }
  481. charCount.textContent = len;
  482. // 实时移除字数超限的错误提示(如果之前是因为超限报错)
  483. if (len <= 500 && feedbackContentError && feedbackContentError.style.display === 'block' && feedbackContentError.textContent.includes('最多500字')) {
  484. // 但避免移除其他类型错误,通过文本内容判断
  485. if (feedbackContentError.textContent.includes('最多500字')) {
  486. feedbackContentError.style.display = 'none';
  487. }
  488. }
  489. });
  490. // 增加blur时再次校验,保证用户粘贴超长内容时提示
  491. fcontent.addEventListener('blur', function () {
  492. let len = this.value.length;
  493. if (len > 500) {
  494. this.value = this.value.substring(0, 500);
  495. charCount.textContent = 500;
  496. showError(feedbackContentError, '反馈内容不能超过500字');
  497. }
  498. });
  499. }
  500. // 移动端菜单切换
  501. const mobileMenuBtn = document.getElementById('mobileMenuBtn');
  502. if (mobileMenuBtn) {
  503. mobileMenuBtn.addEventListener('click', function () {
  504. const menu = document.getElementById('mobileMenu');
  505. menu.classList.toggle('hidden');
  506. const icon = this.querySelector('i');
  507. if (icon.classList.contains('fa-bars')) {
  508. icon.classList.replace('fa-bars', 'fa-times');
  509. } else {
  510. icon.classList.replace('fa-times', 'fa-bars');
  511. }
  512. });
  513. }
  514. // 表单提交处理 - 调用API保存数据,成功后显示弹窗,额外校验500字限制
  515. form.addEventListener('submit', async function (e) {
  516. e.preventDefault();
  517. // 前端校验
  518. hideAllErrors();
  519. const name = document.getElementById('fusername').value.trim();
  520. const countryCode = document.getElementById('countryinfo').value;
  521. const phoneRaw = document.getElementById('umoblie').value.trim();
  522. const wechat = document.getElementById('fwechat').value.trim();
  523. const email = document.getElementById('femail').value.trim();
  524. const feedbackTypeText = document.getElementById('ftype').value;
  525. let feedbackContent = document.getElementById('fcontent').value.trim();
  526. let isValid = true;
  527. // 姓名校验
  528. if (!name) {
  529. showError(nameError, '请输入您的姓名');
  530. isValid = false;
  531. }
  532. // 手机号校验
  533. if (!phoneRaw || !isValidPhone(phoneRaw)) {
  534. showError(phoneError, '请输入有效的手机号码');
  535. isValid = false;
  536. }
  537. // 邮箱校验
  538. if (!email || !isValidEmail(email)) {
  539. showError(emailError, '请输入有效的邮箱地址');
  540. isValid = false;
  541. }
  542. // 反馈内容校验: 不能为空且长度必须在10~500之间
  543. if (!feedbackContent) {
  544. showError(feedbackContentError, '请输入反馈内容(至少10个字符,最多500字)');
  545. isValid = false;
  546. } else {
  547. // 重新获取实际内容(防止中间有特殊空格导致长度偏差)
  548. const rawLen = feedbackContent.length;
  549. if (rawLen < 10) {
  550. showError(feedbackContentError, '反馈内容至少需要10个字符,请详细描述');
  551. isValid = false;
  552. } else if (rawLen > 500) {
  553. // 如果因为某些意外情况(例如直接通过开发者工具修改)导致超长,再次截断并提示
  554. feedbackContent = feedbackContent.substring(0, 500);
  555. document.getElementById('fcontent').value = feedbackContent;
  556. charCount.textContent = 500;
  557. showError(feedbackContentError, '反馈内容不能超过500字,已自动截断');
  558. isValid = false;
  559. }
  560. }
  561. if (!isValid) {
  562. return;
  563. }
  564. // 清理手机号
  565. const cleanedPhone = cleanPhoneNumber(phoneRaw);
  566. // 组装请求参数
  567. const requestData = {
  568. name: name,
  569. code: countryCode,
  570. tel: cleanedPhone,
  571. email: email,
  572. feedback_content: feedbackContent,
  573. feedback_type: getFeedbackTypeValue(feedbackTypeText)
  574. };
  575. // 微信ID有值才传递
  576. if (wechat) {
  577. requestData.weChat = wechat;
  578. }
  579. // 显示加载状态
  580. submitBtn.disabled = true;
  581. loadingIndicator.classList.remove('hidden');
  582. try {
  583. const result = await registerMemberApi(requestData);
  584. if (result.code === 200) {
  585. // API调用成功,显示成功弹窗
  586. showSuccessModal();
  587. // 清空表单
  588. form.reset();
  589. // 重置字符计数
  590. if (charCount) charCount.textContent = '0';
  591. // 清空所有隐藏错误显示
  592. hideAllErrors();
  593. } else {
  594. alert('提交失败:' + (result.msg || '请稍后重试'));
  595. }
  596. } catch (error) {
  597. console.error('提交出错:', error);
  598. alert('网络错误或接口异常,请稍后重试');
  599. } finally {
  600. submitBtn.disabled = false;
  601. loadingIndicator.classList.add('hidden');
  602. }
  603. });
  604. // 页面加载动画
  605. document.addEventListener('DOMContentLoaded', function () {
  606. document.querySelectorAll('.fade-in').forEach(el => {
  607. el.style.opacity = '1';
  608. });
  609. // 确保字符计数初始正确
  610. if (fcontent && charCount) {
  611. charCount.textContent = fcontent.value.length;
  612. }
  613. });
  614. </script>
  615. </body>
  616. </html>