main.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. // 載入共用 template
  2. $('#navbar').load('../../template/navbar.html');
  3. $('#footer').load('../../template/footer.html');
  4. $('#btn-box').load('../../template/button.html');
  5. $('#topCarousel').load('../../template/top_carousel.html');
  6. let assignOrder = ""; // 當前排序
  7. // new, hot, recommend 排序 (預設推薦)
  8. $(".search-btn-filter button").click(function () {
  9. // 切換選取狀態
  10. $('.search-btn-filter').find('.active').removeClass('active');
  11. $(this).addClass('active');
  12. assignOrder = $(this).attr('id');
  13. dataSearch();
  14. });
  15. let page = 1; // 當前頁數
  16. let pageSize = 18; // 每頁數量
  17. let isFirstLoad = true; // 初始載入
  18. let assignTab = "caseTab"; // 指定類別 (預設為空間靈感)
  19. // 列表篩選
  20. async function dataSearch(type = "") {
  21. let url;
  22. $('#dataSpinner').show();
  23. $('#dataList').hide();
  24. switch (assignTab) {
  25. case "caseTab":
  26. url = `https://m3.hhh.com.tw:18673/case_search?page=${page}&page_size=${pageSize}`;
  27. break;
  28. case "designerTab":
  29. url = `https://m3.hhh.com.tw:18673/designer_search?page=${page}&page_size=${pageSize}`;
  30. break;
  31. case "videoTab":
  32. url = `https://m3.hhh.com.tw:18673/video_search?page=${page}&page_size=${pageSize}`;
  33. break;
  34. case "columnTab":
  35. url = `https://m3.hhh.com.tw:18673/column_search?page=${page}&page_size=${pageSize}`;
  36. break;
  37. case "builderTab":
  38. url = `https://m3.hhh.com.tw:18673/builder_search?page=${page}&page_size=${pageSize}`;
  39. break;
  40. default:
  41. break;
  42. }
  43. let input = $(".keywords").val();
  44. if (input !== "") {
  45. let isExist = filterList.some((item) => item.id === "keyword"); // 判斷是否已存在關鍵字
  46. const newItem = {
  47. id: "keyword",
  48. text: "關鍵字",
  49. value: input
  50. };
  51. if (!isExist) {
  52. filterList.push(newItem);
  53. createFilterHtml(newItem);
  54. } else {
  55. // 移除原本關鍵字
  56. $('.budget p.me-1').each(function () {
  57. if ($(this).text().includes('關鍵字')) {
  58. $(this).closest('.me-3').remove();
  59. }
  60. });
  61. if (filterList.length === 0) {
  62. $('#removeResultBtn').hide();
  63. }
  64. filterList = filterList.filter(item => item.text !== "關鍵字");
  65. filterList.push(newItem);
  66. createFilterHtml(newItem);
  67. }
  68. $(".keywords").val("")
  69. }
  70. if (filterList.length) {
  71. filterList.map(item => {
  72. if (item.id === "fee") {
  73. // 裝修預算
  74. switch (item.value) {
  75. case "100萬以下":
  76. url += `&${item.id}=1`;
  77. break;
  78. case "101~200萬":
  79. url += `&${item.id}=2`;
  80. break;
  81. case "201~300萬":
  82. url += `&${item.id}=3`;
  83. break;
  84. case "301萬以上":
  85. url += `&${item.id}=4`;
  86. break;
  87. default:
  88. break;
  89. }
  90. } else if (item.id === "area") {
  91. // 房屋坪數
  92. switch (item.value) {
  93. case "20坪以下":
  94. url += `&${item.id}=1`;
  95. break;
  96. case "21-30坪":
  97. url += `&${item.id}=2`;
  98. break;
  99. case "31-50坪":
  100. url += `&${item.id}=3`;
  101. break;
  102. case "51坪以上":
  103. url += `&${item.id}=4`;
  104. break;
  105. default:
  106. break;
  107. }
  108. } else if (item.id === 'budget') {
  109. switch (item.value) {
  110. case "100萬以下":
  111. url += `&${item.id}=1`;
  112. break;
  113. case "100~200萬":
  114. url += `&${item.id}=2`;
  115. break;
  116. case "200~300萬":
  117. url += `&${item.id}=3`;
  118. break;
  119. case "300~400萬":
  120. url += `&${item.id}=4`;
  121. break;
  122. case "400~500萬":
  123. url += `&${item.id}=5`;
  124. break;
  125. case "500萬以上":
  126. url += `&${item.id}=6`;
  127. break;
  128. default:
  129. break;
  130. }
  131. } else {
  132. url += `&${item.id}=${item.value}`;
  133. }
  134. });
  135. }
  136. // 排序
  137. if (assignOrder === "") {
  138. // 預設
  139. if (assignTab === "designerTab") {
  140. url += "&order_by=recommend";
  141. } else {
  142. url += "&order_by=new";
  143. }
  144. } else {
  145. url += `&order_by=${assignOrder}`;
  146. }
  147. try {
  148. const response = await axios.get(url);
  149. console.log('response.data >>', response.data);
  150. let totalPages = Math.ceil(totalCount / pageSize);
  151. if (totalPages) {
  152. $('.filter-list .pagination').show();
  153. setPagination(totalPages); // 分頁處理
  154. } else {
  155. $('.filter-list .pagination').hide();
  156. }
  157. let resultHtml = '';
  158. switch (assignTab) {
  159. case "caseTab":
  160. if (response.data.cases.length) {
  161. response.data.cases.forEach((item) => {
  162. let tagList = item.CaseTag.split(',');
  163. let tagsHtml = '';
  164. tagList.forEach((tag) => {
  165. if (tag !== "") {
  166. tagsHtml += `<span class="tag-item" data-tag="${tag}">${tag}</span>`;
  167. }
  168. });
  169. resultHtml += `
  170. <div class="col-md-4 mb-4">
  171. <a href="${item.DesignerLink}">
  172. <div class="card lists-card">
  173. <img src="${item.CaseCoverImg}" class="cover-img" alt="${item.DesignerName} ${item.DesignerTitle}">
  174. <div class="card-body d-flex flex-column">
  175. <div class="d-flex align-items-center">
  176. <div class="person-img me-3 me-md-2 me-lg-3" style="background-image: url('${item.DesignerCoverImg}');"></div>
  177. <section>
  178. <h5 class="text-muted mb-2">${item.DesignerTitle}</h5>
  179. <h6 class="mb-0 text-dark">
  180. <span class="font-weight-bold">
  181. ${item.DesignerName}
  182. </span>
  183. 設計師
  184. </h6>
  185. </section>
  186. </div>
  187. <p class="mt-3 text-dark title">${item.CaseTitle}</p>
  188. <div class="tags-container my-3 me-auto">${tagsHtml}</div>
  189. <small class="d-block ms-auto mt-auto date-item">上架日期 ${item.CaseSdate}</small>
  190. </div>
  191. </div>
  192. </a>
  193. </div>`;
  194. });
  195. } else {
  196. resultHtml += "<p class='text-center mt-5'>找不到符合的資料,請重新搜尋。</p>"
  197. }
  198. let caseCount = response.data.total_count.toLocaleString();
  199. $("#caseCount").html(`(${caseCount})`);
  200. break;
  201. case "designerTab":
  202. if (response.data.designers.length) {
  203. response.data.designers.forEach((item) => {
  204. resultHtml += `
  205. <div class="col-md-4 mb-4">
  206. <a href="${item.DesignerLink}">
  207. <div class="card lists-card">
  208. <img src="${item.CaseCoverImg}" class="cover-img" alt="${item.DesignerName} ${item.DesignerTitle}">
  209. <div class="card-body d-flex align-items-center">
  210. <div class="person-img me-3 me-md-2 me-lg-3" style="background-image: url('${item.DesignerCoverImg}');"></div>
  211. <section>
  212. <h5 class="text-muted mb-2">${item.DesignerTitle}</h5>
  213. <h6 class="mb-0 text-dark">
  214. <span class="font-weight-bold">
  215. ${item.DesignerName}
  216. </span>
  217. 設計師
  218. </h6>
  219. </section>
  220. </div>
  221. </div>
  222. </a>
  223. </div>`;
  224. });
  225. } else {
  226. resultHtml += "<p class='text-center mt-5'>找不到符合的資料,請重新搜尋。</p>"
  227. }
  228. let designerCount = response.data.total_count.toLocaleString();
  229. $("#designerCount").html(`(${designerCount})`);
  230. break;
  231. case "videoTab":
  232. if (response.data.videos.length) {
  233. response.data.videos.forEach((item) => {
  234. let tagsHtml = '';
  235. item.VideoTag.forEach((tag) => {
  236. if (tag !== "") {
  237. tagsHtml += `<span class="tag-item" data-tag="${tag}">${tag}</span>`;
  238. }
  239. });
  240. resultHtml += `
  241. <div class="col-md-4 mb-4">
  242. <a href="${item.DesignerLink}">
  243. <div class="card lists-card">
  244. <img src="${item.VideoCoverImg}" class="video-cover-img" alt="${item.DesignerName} ${item.DesignerTitle}">
  245. <div class="card-body d-flex flex-column align-items-center">
  246. <section class="d-flex align-items-center w-100">
  247. <div class="person-img me-3 me-md-2 me-lg-3" style="background-image: url('${item.DesignerCoverImg}');"></div>
  248. <h5 class="text-muted mb-2">${item.DesignerTitle}</h5>
  249. </section>
  250. <h3 class="my-3 video-title">${item.VideoTitle}</h3>
  251. <div class="tags-container mt-2 me-auto">${tagsHtml}</div>
  252. </div>
  253. </div>
  254. </a>
  255. </div>`;
  256. });
  257. } else {
  258. resultHtml += "<p class='text-center mt-5'>找不到符合的資料,請重新搜尋。</p>"
  259. }
  260. let videoCount = response.data.total_count.toLocaleString();
  261. $("#videoCount").html(`(${videoCount})`);
  262. break;
  263. case "columnTab":
  264. if (response.data.columns.length) {
  265. // 取得當前日期並計算三天前的日期
  266. const currentDate = new Date();
  267. const threeDaysAgo = new Date();
  268. threeDaysAgo.setDate(currentDate.getDate() - 3);
  269. response.data.columns.forEach((item, index) => {
  270. // 將 ColumnDate 轉換成日期物件
  271. const columnDate = new Date(item.ColumnDate);
  272. // 判斷 ColumnDate 是否在三天內
  273. const isNew = columnDate >= threeDaysAgo && columnDate <= currentDate;
  274. const newItemClass = isNew ? '' : 'd-none'; // 非三天內則隱藏 New 標籤
  275. let tagList = item.ColumnTag.split(',');
  276. let tagsHtml = '';
  277. tagList.forEach((tag) => {
  278. if (tag !== "") {
  279. tagsHtml += `<span class="tag-item" data-tag="${tag}">${tag}</span>`;
  280. }
  281. });
  282. resultHtml += `
  283. <div class="col-md-4 mb-4">
  284. <a href="${item.ColumnLink}">
  285. <div class="card lists-card h-auto">
  286. <img src="${item.ColumnCoverImg}" class="cover-img" alt="${item.ColumnTitle}">
  287. <div class="card-body d-flex flex-column">
  288. <h5 class="text-dark title">${item.ColumnTitle}</h5>
  289. <div class="tags-container columns-tag mt-3 me-auto">${tagsHtml}</div>
  290. </div>
  291. <span class="new-item ${newItemClass}">NEW</span>
  292. </div>
  293. </a>
  294. </div>`;
  295. });
  296. $('#dataList').append(resultHtml);
  297. } else {
  298. resultHtml += "<p class='text-center mt-5'>找不到符合的資料,請重新搜尋。</p>"
  299. }
  300. let columnCount = response.data.total_count.toLocaleString();
  301. $("#columnCount").html(`(${columnCount})`);
  302. break;
  303. case "builderTab":
  304. if (response.data.videos.length) {
  305. response.data.videos.forEach((item) => {
  306. resultHtml += `
  307. <div class="col-md-4 mb-4">
  308. <a href="${item.DesignerLink}">
  309. <div class="card lists-card">
  310. <div class="position-relative">
  311. <img src="../../img/icon/play.svg" class="play-img${item.Is_video === '0' ? ' d-none' : ''}" alt="play-img">
  312. <img src="${item.BuilderCoverImg}" class="cover-img" alt="${item.BuilderTitle}">
  313. </div>
  314. <div class="card-body p-4">
  315. <section>
  316. <h5 class="text-dark">${item.BuilderTitle}</h5>
  317. <p class="text-dark my-3">${item.BuilderDescr}</p>
  318. <h6 class="mb-0 text-muted fw-normal">
  319. ${item.BuilderAddress}
  320. </h6>
  321. </section>
  322. </div>
  323. </div>
  324. </a>
  325. </div>`;
  326. });
  327. } else {
  328. resultHtml += "<p class='text-center mt-5'>找不到符合的資料,請重新搜尋。</p>"
  329. }
  330. let builderCount = response.data.total_count.toLocaleString();
  331. $("#builderCount").html(`(${builderCount})`);
  332. break;
  333. default:
  334. break;
  335. }
  336. // if (response.data.videos.length) {
  337. // response.data.videos.forEach((item) => {
  338. // resultHtml += `
  339. // <div class="col-md-4 mb-4">
  340. // <a href="${item.DesignerLink}">
  341. // <div class="card lists-card">
  342. // <div class="position-relative">
  343. // <img src="../../img/icon/play.svg" class="play-img${item.Is_video === '0' ? ' d-none' : ''}" alt="play-img">
  344. // <img src="${item.BuilderCoverImg}" class="cover-img" alt="${item.BuilderTitle}">
  345. // </div>
  346. // <div class="card-body p-4">
  347. // <section>
  348. // <h5 class="text-dark">${item.BuilderTitle}</h5>
  349. // <p class="text-dark my-3">${item.BuilderDescr}</p>
  350. // <h6 class="mb-0 text-muted fw-normal">
  351. // ${item.BuilderAddress}
  352. // </h6>
  353. // </section>
  354. // </div>
  355. // </div>
  356. // </a>
  357. // </div>`;
  358. // });
  359. // } else {
  360. // resultHtml += "<p class='text-center mt-5'>找不到符合的資料,請重新搜尋。</p>"
  361. // }
  362. $('#dataList').html(resultHtml);
  363. setTimeout(() => {
  364. setTotalCount();
  365. $('#dataList').show();
  366. $('#dataSpinner').hide();
  367. }, 100)
  368. // 更新初始載入狀態
  369. if (isFirstLoad) {
  370. isFirstLoad = false;
  371. }
  372. } catch (error) {
  373. console.log("error", error);
  374. }
  375. }
  376. dataSearch();
  377. // 取得全部符合筆數
  378. async function getAllSearchCount() {
  379. let url = "https://m3.hhh.com.tw:18673/all_search_count";
  380. try {
  381. const response = await axios.get(url);
  382. console.log('response.data', response.data);
  383. $("#caseCount").text(`(${response.data.case_count.toLocaleString()})`)
  384. $("#designerCount").text(`(${response.data.designer_count.toLocaleString()})`)
  385. $("#videoCount").text(`(${response.data.video_count.toLocaleString()})`)
  386. $("#columnCount").text(`(${response.data.column_count.toLocaleString()})`)
  387. $("#builderCount").text(`(${response.data.builder_count.toLocaleString()})`)
  388. // 數量加總
  389. let total = response.data.designer_count + response.data.column_count + response.data.case_count + response.data.builder_count + response.data.video_count;
  390. $('#totalCount').text(total.toLocaleString());
  391. } catch (error) {
  392. console.log("error", error);
  393. }
  394. }
  395. getAllSearchCount();
  396. // 計算總筆數
  397. function setTotalCount() {
  398. // 將各類別總筆數轉為數字
  399. let caseCount = parseInt($('#caseCount').text().replace(/[(),]/g, ''), 10);
  400. let designerCount = parseInt($('#designerCount').text().replace(/[(),]/g, ''), 10);
  401. let videoCount = parseInt($('#videoCount').text().replace(/[(),]/g, ''), 10);
  402. let columnCount = parseInt($('#columnCount').text().replace(/[(),]/g, ''), 10);
  403. let builderCount = parseInt($('#builderCount').text().replace(/[(),]/g, ''), 10);
  404. // 將各個數字相加
  405. let total = caseCount + designerCount + videoCount + builderCount + columnCount;
  406. $('#totalCount').text(total.toLocaleString());
  407. console.log('Total:', total);
  408. }
  409. // 切換 Tab
  410. $('.search-tab-list .nav-item').click(function (e) {
  411. getAllSearchCount(); // 重新取得總筆數
  412. // 使用 closest() 找到最近的 button 元素
  413. let button = $(e.target).closest('button');
  414. assignTab = button.attr('id');
  415. console.log('assignTab', assignTab);
  416. if (assignTab === "designerTab") {
  417. $('.search-btn-filter').find('.active').removeClass('active');
  418. $("#recommend").addClass('active');
  419. $("#recommendItem").show();
  420. } else {
  421. $('.search-btn-filter').find('.active').removeClass('active');
  422. $("#new").addClass('active');
  423. $("#recommendItem").hide();
  424. }
  425. // 全部清除
  426. filterList.length = 0; // 清空篩選陣列
  427. $('.keywords').val(''); // 清空搜尋欄位
  428. $('#removeResultBtn').hide(); // 隱藏全部清除按鈕
  429. $('.search-tab-result').empty(); // 清空篩選條件 dom
  430. // 取消選取狀態
  431. $('.filter-list input[type="radio"]').prop('checked', false);
  432. $('.search-tab').removeClass('active');
  433. dataSearch(); // 篩選
  434. });
  435. // 次要類別選單
  436. let subCategory = [
  437. {
  438. title: "編輯精選",
  439. list: ["居家趨勢", "人氣排行", "建築設計", "風格選店", "公益活動", "展演資訊"]
  440. },
  441. {
  442. title: "居家設計",
  443. list: ["小宅規劃", "老屋翻新", "風格營造", "配色佈置", "好宅特輯", "設計提案"]
  444. },
  445. {
  446. title: "裝修前線",
  447. list: ["新聞最前線", "預算分配", "施工流程", "建材知識", "裝潢撇步"]
  448. },
  449. {
  450. title: "生活PLUS",
  451. list: ["居家風水", "家事清潔", "收納技巧", "改造修繕", "退休好幸福"]
  452. },
  453. {
  454. title: "品牌好物",
  455. list: ["家具家飾", "美型家電", "推薦廚衛", "居家好物", "優質建材", "品牌新訊"]
  456. },
  457. {
  458. title: "房市焦點",
  459. list: ["房市新聞", "建案特搜", "買屋賣屋", "房貸稅務", "租房須知"]
  460. }
  461. ];
  462. // 專欄文章分類
  463. $("#pills-column #mainCategory .form-check").click(function (e) {
  464. console.log('e >>', e);
  465. let btnText = $(e.target).text().replace(/\s+/g, ''); // 取得主分類
  466. console.log('btnText', btnText);
  467. // 檢查陣列中是否有次分類
  468. let hasSubCategory = filterList.find(item => item.text === "次分類");
  469. if (hasSubCategory) {
  470. // 如果有則移除包含該 DOM 元素
  471. $('span.budget:contains("次分類")').closest('span.me-3').remove();
  472. filterList = filterList.filter(item => item.text !== "次分類");
  473. }
  474. let subHtml = [];
  475. subCategory.map(item => {
  476. if (item.title === btnText) {
  477. item.list.forEach(item => {
  478. let dom = `
  479. <li onclick="clickSubBtn(event, '${item}')">
  480. <div class="form-check">
  481. <input class="form-check-input" type="radio" name="sub_type">
  482. <label class="form-check-label">
  483. ${item}
  484. </label>
  485. </div>
  486. </li>`;
  487. subHtml.push(dom);
  488. })
  489. $('#subCategory ul').html(subHtml);
  490. }
  491. })
  492. $("#subCategory").show();
  493. })
  494. function clickSubBtn(e, item) {
  495. console.log('clickSubBtn', e, item);
  496. let currentElement = $(e.currentTarget);
  497. currentElement.find('.form-check-input').prop('checked', true);
  498. // 取得 radio 按鈕的 label
  499. let radioLabel = currentElement.find('.form-check-label').text().trim().replace(/\s+/g, ' '); // 移除換行空白
  500. // 取上一層 search-tab 按鈕文字
  501. let buttonValue = currentElement.closest('.dropdown').find('.search-tab').text().trim();
  502. let buttonId = currentElement.closest('.dropdown').find('.search-tab').attr('id');
  503. console.log('buttonValue>>', buttonValue);
  504. console.log('buttonId>>', buttonId);
  505. console.log('radioLabel>>', radioLabel);
  506. updateSelectedOptions(buttonId, buttonValue, radioLabel);
  507. }