123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- <template>
- <div class="w-full h-[55px] sm:h-[72px]"></div>
- <div
- class="max-w-full px-4 py-16 md:px-8 lg:px-10 bg-gradient-to-br from-gray-900 via-gray-900 to-black text-gray-300 min-h-screen"
- >
- <div class="max-w-screen-xl mx-auto">
- <h1 class="text-4xl md:text-6xl mb-12 text-center font-normal text-white">
- {{ $t("faq.title") }}
- </h1>
-
- <!-- Search Bar -->
- <div class="mb-12 max-w-xl mx-auto">
- <div class="relative">
- <input
- type="search"
- v-model="searchTerm"
- :placeholder="$t('faq.searchPlaceholder')"
- class="block w-full appearance-none rounded-lg border border-gray-600 bg-gray-700/50 px-4 py-3 pl-10 pr-4 text-base text-gray-100 placeholder-gray-400 shadow-inner transition duration-200 ease-in-out focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/50 focus:ring-offset-2 focus:ring-offset-gray-900"
- />
- <div
- class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- class="h-5 w-5 text-gray-400"
- viewBox="0 0 20 20"
- fill="currentColor"
- >
- <path
- fill-rule="evenodd"
- d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
- clip-rule="evenodd"
- />
- </svg>
- </div>
- </div>
- </div>
-
- <!-- FAQ Accordion -->
- <div class="space-y-5">
- <div
- v-for="faq in filteredFaqs"
- :key="faq.id"
- class="relative border rounded-xl overflow-hidden shadow-lg backdrop-blur-sm transition-all duration-300 ease-in-out group"
- :class="[
- openAccordionIds.has(faq.id)
- ? 'bg-gray-750/70 border-blue-500/60 shadow-blue-500/20'
- : 'bg-gray-800/60 border-gray-700 hover:border-blue-500/40 hover:bg-gray-750/70',
- ]"
- >
- <button
- @click="toggleAccordion(faq.id)"
- class="flex w-full items-center justify-between px-6 py-5 text-left text-lg font-medium text-gray-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 focus-visible:ring-offset-gray-800 transition-colors duration-200"
- :class="{ 'bg-gray-700/50': openAccordionIds.has(faq.id) }"
- :aria-expanded="openAccordionIds.has(faq.id)"
- :aria-controls="`faq-answer-${faq.id}`"
- >
- <span class="pr-4">{{ faq.question }}</span>
- <!-- Plus/Minus Icon -->
- <div
- class="relative h-6 w-6 flex-shrink-0 text-blue-400 group-hover:text-blue-300"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- class="absolute h-6 w-6 transition-opacity duration-300 ease-in-out"
- :class="
- openAccordionIds.has(faq.id) ? 'opacity-0' : 'opacity-100'
- "
- fill="none"
- viewBox="0 0 24 24"
- stroke="currentColor"
- stroke-width="2"
- >
- <path
- stroke-linecap="round"
- stroke-linejoin="round"
- d="M12 4v16m8-8H4"
- />
- </svg>
- <svg
- xmlns="http://www.w3.org/2000/svg"
- class="absolute h-6 w-6 transition-opacity duration-300 ease-in-out"
- :class="
- openAccordionIds.has(faq.id) ? 'opacity-100' : 'opacity-0'
- "
- fill="none"
- viewBox="0 0 24 24"
- stroke="currentColor"
- stroke-width="2"
- >
- <path
- stroke-linecap="round"
- stroke-linejoin="round"
- d="M20 12H4"
- />
- </svg>
- </div>
- </button>
- <transition
- enter-active-class="transition-[grid-template-rows,opacity] ease-in-out duration-300"
- enter-from-class="grid-template-rows-[0fr] opacity-0"
- enter-to-class="grid-template-rows-[1fr] opacity-100"
- leave-active-class="transition-[grid-template-rows,opacity] ease-in-out duration-300"
- leave-from-class="grid-template-rows-[1fr] opacity-100"
- leave-to-class="grid-template-rows-[0fr] opacity-0"
- >
- <div
- v-show="openAccordionIds.has(faq.id)"
- :id="`faq-answer-${faq.id}`"
- class="grid overflow-hidden"
- role="region"
- >
- <div class="overflow-hidden">
- <div
- class="px-6 pt-4 pb-8 text-base text-gray-300 leading-relaxed"
- >
- <div
- class="prose prose-invert max-w-none prose-p:text-gray-300 prose-a:text-blue-400 hover:prose-a:text-blue-300"
- >
- <p v-html="faq.answer"></p>
- </div>
- </div>
- </div>
- </div>
- </transition>
- </div>
-
- <div
- v-if="filteredFaqs.length === 0"
- class="text-center text-gray-400 py-8"
- >
- {{ $t("faq.noResults") }}
- </div>
- </div>
- </div>
- </div>
- </template>
-
- <script setup lang="ts">
- import { ref, computed } from "vue";
- import { useI18n } from "vue-i18n";
-
- const { t } = useI18n();
- const searchTerm = ref("");
- const openAccordionIds = ref<Set<string>>(new Set());
-
- // Define FAQ item type with actual strings
- interface FaqItem {
- id: string;
- question: string;
- answer: string;
- }
-
- // Placeholder FAQ data with actual strings (replace with your real data)
- const faqs = ref<FaqItem[]>([
- {
- id: "faq-1",
- question: "如何购买 Hanye 产品?", // Example Question 1
- answer:
- "您可以通过我们的官方在线商店或授权的零售商处购买 Hanye 产品。我们建议您在官方渠道购买以确保正品和售后服务。", // Example Answer 1
- },
- {
- id: "faq-2",
- question: "产品保修期是多久?",
- answer:
- "不同产品的保修期可能不同,请参考具体产品的说明页面或联系我们的客服获取详细信息。通常固态硬盘提供3-5年保修,内存条提供终身保固。",
- },
- {
- id: "faq-3",
- question: "如何申请售后服务?",
- answer:
- "如果您需要售后服务,请准备好您的购买凭证,并通过我们的官方网站提交售后申请或直接联系客服中心。",
- },
- {
- id: "faq-4",
- question: "Hanye SSD 是否兼容我的电脑?",
- answer:
- "Hanye SSD 兼容大多数台式机和笔记本电脑。请确认您的设备支持相应的接口(如 SATA 或 NVMe)和规格。具体兼容性列表请参考产品页面。",
- },
- {
- id: "faq-5",
- question: "忘记密码怎么办?",
- answer:
- '如果是指 Hanye 相关的在线服务账户密码,请使用"忘记密码"功能进行重置。如果是加密 U 盘或 SSD 的密码,很抱歉,为了数据安全,我们无法提供密码破解服务。',
- },
- ]);
-
- // Filter FAQs based on actual string content
- const filteredFaqs = computed(() => {
- if (!searchTerm.value) {
- return faqs.value;
- }
- const lowerSearchTerm = searchTerm.value.toLowerCase();
- return faqs.value.filter(
- (faq: FaqItem) =>
- faq.question.toLowerCase().includes(lowerSearchTerm) ||
- faq.answer.toLowerCase().includes(lowerSearchTerm)
- );
- });
-
- // Toggle accordion item (modified for Set)
- const toggleAccordion = (id: string) => {
- if (openAccordionIds.value.has(id)) {
- openAccordionIds.value.delete(id);
- } else {
- openAccordionIds.value.add(id);
- }
- };
-
- // SEO (Still uses i18n)
- useHead({
- title: t("faq.meta.title"),
- meta: [
- {
- name: "description",
- content: t("faq.meta.description"),
- },
- ],
- });
- </script>
|