Browse Source

2025年06月04日:01)完成 “文章详情” 和 “常见问题” 静态页面开发;02)完成 “@/utils/request.ts” 文件内容填充。

yankun 1 tháng trước cách đây
mục cha
commit
7bd3ccd7b1

+ 9 - 0
src/apis/system.ts

@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+
+
+export const getInfo = (params: Object) => request({
+  url: '/api/cate/getCateListProduct',
+  method: 'get',
+  params: params
+})

+ 3 - 3
src/locale/index.ts

@@ -5,7 +5,7 @@ import zh from './lang/zh'
 
 // 获取当前语言
 export function getCurrentLang(): string | null {
-  return !!localStorage.getItem('locale') && localStorage.getItem('locale') !== 'null' && localStorage.getItem('locale') !== 'undefine' ? localStorage.getItem('locale') : 'zhCN'
+  return !!localStorage.getItem('locale') && localStorage.getItem('locale') !== 'null' && localStorage.getItem('locale') !== 'undefine' ? localStorage.getItem('locale') : 'zh-CN'
 }
 
 
@@ -13,10 +13,10 @@ export function getCurrentLang(): string | null {
 const i18n = createI18n({
   legacy: false,
   locale: (getCurrentLang() as string),
-  fallbackLocale: 'zhCN',
+  fallbackLocale: 'zh-CN',
   messages: {
     en: en,
-    zhCN: zh,
+    "zh-CN": zh,
   },
 });
 

+ 22 - 1
src/locale/lang/en.ts

@@ -28,7 +28,8 @@ export default {
     "澳大利亚": "Australia",
     "意大利": "Italy",
     "囧二": "Guang Er",
-    
+    updateTimeTxt: 'Updated on {updateTime}'
+
   },
   textLink: {
     "常见问题": "FAQ",
@@ -63,5 +64,25 @@ export default {
     "如果你想买其他东西,没有比 Vava buy 更好的了": "If you want to buy anything else, there's no better option than Vava Buy",
     "非常易于使用,包装很精美,会收获很多惊喜": "Very easy to use, with exquisite packaging, and you will receive many surprises",
     "我们使用 cookie 来提供更好的在线体验。 访问和使用 VAVA BUY.com,即表示您同意我们使用 Cookie。 通过阅读我们的条款和条件、使用条款、 和隐私政策。": "We use cookies to provide a better online experience. By visiting and using VAVA BUY.com, you are agreeing to our use of cookies. Please read our terms and conditions, usage terms, and privacy policy.",
+  },
+  questionPage: {
+    bannerTitle: 'FAQ',
+    bannerDesc: 'We will be here to answer all your questions',
+    bannerSearchPlaceholder: 'Please enter the key words of your question...',
+    bannerSearchBtn: 'Search',
+    searchResultTitle: 'Search results ({count} items)',
+    questionCategoryMenuBtn: 'Classification',
+    questionCategoryCountTxt: '{count} questions',
+    questionDrawerTitle: 'Problem classification',
+    questionTagHot: 'Hot',
+    questionTagNew: 'New',
+    questionReadCount: 'Read {count} times',
+    questionDetailBackbtn: 'Back',
+    contactTitle: "Didn't find the answer you need?",
+    contactDesc: 'Our customer service team is always at your service',
+    contactForPhoneTitle: 'Telephone support',
+    contactForPhoneWorkTime: 'Monday to Sunday 9:00-18:00',
+    contactForEmailTitle: 'Email',
+    contactForEmailWorkTime: 'We will reply within 24 hours',
   }
 }

+ 21 - 0
src/locale/lang/zh.ts

@@ -28,6 +28,7 @@ export default {
     "澳大利亚": "澳大利亚",
     "意大利": "意大利",
     "囧二": "囧二",
+    updateTimeTxt: '更新于 {updateTime}'
   },
   textLink: {
     "常见问题": "常见问题",
@@ -62,5 +63,25 @@ export default {
     "如果你想买其他东西,没有比 Vava buy 更好的了": "如果你想买其他东西,没有比 Vava buy 更好的了",
     "非常易于使用,包装很精美,会收获很多惊喜": "非常易于使用,包装很精美,会收获很多惊喜",
     "我们使用 cookie 来提供更好的在线体验。 访问和使用 VAVA BUY.com,即表示您同意我们使用 Cookie。 通过阅读我们的条款和条件、使用条款、 和隐私政策。": "我们使用 cookie 来提供更好的在线体验。 访问和使用 VAVA BUY.com,即表示您同意我们使用 Cookie。 通过阅读我们的条款和条件、使用条款、 和隐私政策。",
+  },
+  questionPage: {
+    bannerTitle: '常见问题',
+    bannerDesc: '我们将在这里为您解答所有疑问',
+    bannerSearchPlaceholder: '请输入您的问题关键词...',
+    bannerSearchBtn: '搜索',
+    searchResultTitle: '搜索结果 ({count}条)',
+    questionCategoryMenuBtn: '分类',
+    questionCategoryCountTxt: '{count}个问题',
+    questionDrawerTitle: '常见问题分类',
+    questionTagHot: '热门',
+    questionTagNew: '新',
+    questionReadCount: '阅读 {count} 次',
+    questionDetailBackbtn: '返回列表',
+    contactTitle: '没有找到您需要的答案?',
+    contactDesc: '我们的客服团队随时为您服务',
+    contactForPhoneTitle: '电话支持',
+    contactForPhoneWorkTime: '周一至周日 9:00-18:00',
+    contactForEmailTitle: '电子邮件',
+    contactForEmailWorkTime: '我们会在24小时内回复',
   }
 }

BIN
src/public/images/icons/menu_icon.png


+ 3 - 2
src/router/index.ts

@@ -10,10 +10,11 @@ const routes: Array<RouteRecordRaw> = [
     path: '/',
     name: 'layout',
     component: Layout,
-    redirect: '/home',
+    // redirect: '/home',
     children: [
       {
-        path: 'home',
+        // path: 'home',
+        path: '',
         name: 'home',
         component: Home
       },

+ 2 - 2
src/stores/useSystemStore.ts

@@ -21,13 +21,13 @@ const useSystemStore = defineStore('system', {
   state: (): ISystemState => ({
     locale: getCurrentLang() as string,
     localeList: [
-      { name: '简体中文', value: 'zhCN' },
+      { name: '简体中文', value: 'zh-CN' },
       { name: 'English', value: 'en' },
     ]
   }),
 
   getters: {
-    localeInfo: function(): ILocale {
+    localeInfo: function (): ILocale {
       const result = this.localeList.find((item: ILocale) => (item.value == this.locale))
       return result ? result : this.localeList[0]
     }

+ 35 - 13
src/utils/request.ts

@@ -1,25 +1,47 @@
-import axios from "axios";
+import axios from 'axios'
 
 
 export const BASE_URL = import.meta.env.VITE_BASE_URL
 
 
-const instance = axios.create({
+//用来拦截用的
+axios.defaults.headers.post["Content-Type"] = "application/json;charset=utf-8";
+
+const http = axios.create({
   baseURL: BASE_URL,
   timeout: 1000 * 60 * 5,
 })
 
 
-
+ 
 // 请求拦截器
-
-
-
-
+http.interceptors.request.use(
+  config => {
+    let token = localStorage.getItem('token')
+    if (token) {
+      config.headers.token = token
+    }
+    return config
+  },
+  err => {
+    return Promise.reject(err)
+  }
+)
+ 
 // 响应拦截器
-
-
-
-
-
-export default instance
+http.interceptors.response.use(
+  res => {
+    if (res.data.code == 1) {
+      return Promise.resolve(res.data)
+    }
+    else{
+      return Promise.reject(res.data)
+    }
+  },
+  err => {
+    return Promise.reject(err)
+  }
+)
+ 
+
+export default http

+ 13 - 4
src/views/ArticleDetails/index.vue

@@ -10,7 +10,11 @@
         <span class="author-name">{{ article.author.name }}</span>
       </div> -->
       <div class="publish-time">
-        {{ formatDate(article.publishTime) }}
+        <span>{{
+          $t('system["updateTimeTxt"]', {
+            updateTime: formatDate(article.publishTime, locale),
+          })
+        }}</span>
       </div>
     </div>
 
@@ -26,8 +30,13 @@
   </section>
 </template>
 
-<script setup>
+<script setup lang="ts">
+import { storeToRefs } from 'pinia'
 import { ref } from 'vue'
+import useSystemStore from '@/stores/useSystemStore'
+
+const systemStore = useSystemStore()
+const { locale } = storeToRefs(systemStore)
 
 // 模拟文章数据
 const article = ref({
@@ -91,9 +100,9 @@ const article = ref({
 })
 
 // 格式化日期
-const formatDate = (dateString) => {
+const formatDate = (dateString: string, lang: string) => {
   const options = { year: 'numeric', month: 'long', day: 'numeric' }
-  return new Date(dateString).toLocaleDateString(undefined, options)
+  return new Date(dateString).toLocaleDateString(lang, options as Object)
 }
 </script>
 

+ 19 - 0
src/views/FAQ/css/styles@768.less

@@ -1,6 +1,9 @@
 @media screen and (max-width: 768px) {
   .question-banner {
 
+    margin-bottom: 8px;
+    margin-bottom: 0.5rem;
+
     h1 {
       font-size: 32px;
       font-size: 2rem;
@@ -10,4 +13,20 @@
       font-size: 1rem;
     }
   }
+
+  .question-main-768 {
+    display: block;
+  }
+
+  .question-main-normal {
+    display: none;
+  }
+
+  .detail-content h3 {
+    font-size: 1.375rem !important;
+  }
+
+  .detail-content h4 {
+    font-size: 1.125rem !important;
+  }
 }

+ 233 - 0
src/views/FAQ/hooks/useData.ts

@@ -0,0 +1,233 @@
+import { ref, computed } from 'vue'
+
+
+function useData() {
+
+  // 问题分类
+  const categoryList = ref([
+    { id: 1, name: '账号问题', count: 12 },
+    { id: 2, name: '支付问题', count: 8 },
+    { id: 3, name: '订单问题', count: 15 },
+    { id: 4, name: '产品使用', count: 23 },
+    { id: 5, name: '售后服务', count: 7 },
+    { id: 6, name: '其他问题', count: 5 },
+  ])
+  // 当前选中的分类 ID
+  const activeCategory = ref<string | number>(1)
+
+
+  // 模拟问题数据
+  const questions = ref([
+    {
+      id: 101,
+      categoryId: 1,
+      title: '如何注册账号?',
+      preview: '详细说明注册账号的步骤和注意事项...',
+      content: `
+      <h3>注册账号步骤</h3>
+      <ol>
+        <li>点击网站右上角的"注册"按钮</li>
+        <li>填写您的手机号码或电子邮箱</li>
+        <li>设置登录密码(6-20位字符,包含字母和数字)</li>
+        <li>输入收到的验证码</li>
+        <li>阅读并同意用户协议</li>
+        <li>点击"立即注册"完成注册</li>
+      </ol>
+      <p><strong>注意事项:</strong></p>
+      <ul>
+        <li>请使用常用手机号或邮箱,以便接收重要通知</li>
+        <li>密码请勿设置过于简单</li>
+        <li>如未收到验证码,请检查垃圾邮件或60秒后重新获取</li>
+      </ul>
+    `,
+      updateTime: '2023-05-15',
+      views: 1245,
+      isHot: true,
+      isNew: false,
+    },
+    {
+      id: 102,
+      categoryId: 1,
+      title: '忘记密码怎么办?',
+      preview: '密码找回的几种方法和步骤说明...',
+      content: `
+      <h3>找回密码方法</h3>
+      <p>如果您忘记了密码,可以通过以下方式找回:</p>
+      
+      <h4>方法一:通过手机找回</h4>
+      <ol>
+        <li>在登录页面点击"忘记密码"</li>
+        <li>选择"通过手机找回"</li>
+        <li>输入注册时使用的手机号码</li>
+        <li>获取并输入短信验证码</li>
+        <li>设置新密码并确认</li>
+      </ol>
+      
+      <h4>方法二:通过邮箱找回</h4>
+      <ol>
+        <li>在登录页面点击"忘记密码"</li>
+        <li>选择"通过邮箱找回"</li>
+        <li>输入注册时使用的邮箱地址</li>
+        <li>登录邮箱查收重置密码邮件</li>
+        <li>点击邮件中的链接设置新密码</li>
+      </ol>
+      
+      <p>如果以上方法都无法解决您的问题,请联系客服人员。</p>
+    `,
+      updateTime: '2023-06-02',
+      views: 876,
+      isHot: true,
+      isNew: false,
+    },
+    {
+      id: 201,
+      categoryId: 2,
+      title: '支持哪些支付方式?',
+      preview: '介绍平台目前支持的支付渠道...',
+      content: `
+      <h3>支持的支付方式</h3>
+      <p>我们目前支持以下支付方式:</p>
+      
+      <div class="payment-method">
+        <h4>1. 在线支付</h4>
+        <ul>
+          <li>微信支付</li>
+          <li>支付宝</li>
+          <li>银联在线支付</li>
+          <li>Apple Pay</li>
+        </ul>
+      </div>
+      
+      <div class="payment-method">
+        <h4>2. 银行卡支付</h4>
+        <p>支持以下银行的储蓄卡和信用卡:</p>
+        <ul>
+          <li>中国工商银行</li>
+          <li>中国建设银行</li>
+          <li>中国银行</li>
+          <li>招商银行</li>
+          <li>交通银行等主流银行</li>
+        </ul>
+      </div>
+      
+      <p><strong>注意:</strong>部分银行可能有支付限额,请以银行规定为准。</p>
+    `,
+      updateTime: '2023-04-28',
+      views: 1532,
+      isHot: false,
+      isNew: false,
+    },
+    {
+      id: 301,
+      categoryId: 3,
+      title: '如何查询订单状态?',
+      preview: '订单状态查询的几种途径和方法...',
+      content: `
+      <h3>查询订单状态</h3>
+      <p>您可以通过以下方式查询订单状态:</p>
+      
+      <h4>方法一:网站查询</h4>
+      <ol>
+        <li>登录您的账号</li>
+        <li>点击右上角"我的订单"</li>
+        <li>在订单列表中找到相应订单</li>
+        <li>点击"查看详情"查看订单状态</li>
+      </ol>
+      
+      <h4>方法二:手机APP查询</h4>
+      <ol>
+        <li>打开APP并登录</li>
+        <li>点击底部导航栏"我的"</li>
+        <li>选择"我的订单"</li>
+        <li>查看相应订单状态</li>
+      </ol>
+      
+      <h4>方法三:联系客服查询</h4>
+      <p>如果您无法通过以上方式查询,可以联系客服提供订单号查询。</p>
+      
+      <p><strong>常见订单状态说明:</strong></p>
+      <ul>
+        <li><span class="status waiting">待付款</span> - 订单已生成,等待支付</li>
+        <li><span class="status paid">已支付</span> - 付款成功,等待处理</li>
+        <li><span class="status shipped">已发货</span> - 商品已发出</li>
+        <li><span class="status completed">已完成</span> - 订单交易完成</li>
+        <li><span class="status cancelled">已取消</span> - 订单已取消</li>
+      </ul>
+    `,
+      updateTime: '2023-05-20',
+      views: 2104,
+      isHot: true,
+      isNew: true,
+    },
+  ])
+  // 当前查看的问题详情
+  const currentQuestion = ref(null)
+
+
+  // 搜索查询词
+  const searchQuery = ref('')
+  // 搜索结果
+  const searchResults = ref<Array<typeof questions.value[0]>>([])
+
+
+  // 获取分类名称
+  const getCategoryName = (id: string | number) => {
+    const category = categoryList.value.find((c) => (c.id === id))
+    return category ? category.name : '所有问题'
+  }
+
+  // 切换分类
+  const changeCategory = (categoryId: string | number) => {
+    activeCategory.value = categoryId
+    currentQuestion.value = null
+    searchResults.value = []
+  }
+
+  // 获取当前分类下的问题
+  const questionList = computed(() => {
+    return questions.value.filter((q: any) => q.categoryId === activeCategory.value)
+  })
+
+  // 显示问题详情
+  const showQuestionDetail = (question: any) => {
+    currentQuestion.value = question
+  }
+
+  // 搜索问题
+  const searchQuestions = () => {
+    if (!searchQuery.value.trim()) {
+      searchResults.value = []
+      return
+    }
+
+    const query = searchQuery.value.toLowerCase()
+    searchResults.value = questions.value.filter((q) => {
+      return q.title.toLowerCase().includes(query) || q.preview.toLowerCase().includes(query)
+    })
+    currentQuestion.value = null
+  }
+
+  // 返回问题列表
+  const backToList = () => {
+    currentQuestion.value = null
+  }
+
+  return {
+    categoryList,
+    activeCategory,
+    questionList,
+    currentQuestion,
+    questions,
+    searchQuery,
+    searchResults,
+    getCategoryName,
+    changeCategory,
+    showQuestionDetail,
+    searchQuestions,
+    backToList,
+  }
+}
+
+
+
+export default useData

+ 303 - 261
src/views/FAQ/index.vue

@@ -2,15 +2,15 @@
   <div class="question-container">
     <!-- 顶部横幅 -->
     <div class="question-banner">
-      <h1>常见问题</h1>
-      <p>我们将在这里为您解答所有疑问</p>
+      <h1>{{ $t('questionPage["bannerTitle"]') }}</h1>
+      <p>{{ $t('questionPage["bannerDesc"]') }}</p>
 
       <!-- 搜索框 -->
       <div class="question__search-box">
         <input
           type="text"
           v-model="searchQuery"
-          placeholder="请输入您的问题关键词..."
+          :placeholder="$t(`questionPage['bannerSearchPlaceholder']`)"
           @keyup.enter="searchQuestions"
         />
         <button @click="searchQuestions">
@@ -25,33 +25,168 @@
               d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"
             />
           </svg>
-          搜索
+          {{ $t(`questionPage['bannerSearchBtn']`) }}
         </button>
       </div>
     </div>
 
+    <!-- 主要内容区--移动端 -->
+    <section class="width-1200 question-main-768">
+      <div class="question-main__container question-main__container-768">
+        <!-- 问题列表&内容 -->
+        <div class="question-content">
+          <template v-if="!currentQuestion">
+            <!-- 搜索结果列表 -->
+            <div v-if="searchResults.length > 0" class="search-results question-list">
+              <h2>
+                <span>{{
+                  $t('questionPage["searchResultTitle"]', { count: searchResults.length })
+                }}</span>
+                <div class="category-menu-btn" @click="showCategoryDrawer">
+                  <span>{{ $t('questionPage["questionCategoryMenuBtn"]') }}</span>
+                  <img src="@/public/images/icons/menu_icon.png" alt="" />
+                </div>
+              </h2>
+              <div
+                v-for="item in searchResults"
+                :key="item.id"
+                class="question-item"
+                @click="showQuestionDetail(item)"
+              >
+                <div class="question-title">
+                  {{ item.title }}
+                </div>
+                <div class="question-preview">{{ item.preview }}</div>
+              </div>
+            </div>
+
+            <!-- 问题列表 -->
+            <div v-else class="question-list">
+              <h2>
+                <span>{{ getCategoryName(activeCategory) }}</span>
+                <div class="category-menu-btn" @click="showCategoryDrawer">
+                  <span>{{ $t('questionPage["questionCategoryMenuBtn"]') }}</span>
+                  <img src="@/public/images/icons/menu_icon.png" alt="" />
+                </div>
+              </h2>
+
+              <div
+                v-for="question in questionList"
+                :key="question.id"
+                class="question-item"
+                @click="showQuestionDetail(question)"
+              >
+                <div class="question-title">
+                  {{ question.title }}
+                  <div v-if="question.isHot" class="question-tag hot-tag">
+                    {{ $t('questionPage["questionTagHot"]') }}
+                  </div>
+                  <div v-if="question.isNew" class="question-tag new-tag">
+                    {{ $t('questionPage["questionTagNew"]') }}
+                  </div>
+                </div>
+                <div class="question-preview">{{ question.preview }}</div>
+              </div>
+            </div>
+          </template>
+
+          <!-- 问题详情 -->
+          <div v-else class="question-detail">
+            <div class="detail-footer">
+              <button class="back-btn" @click="backToList">
+                <svg
+                  xmlns="http://www.w3.org/2000/svg"
+                  width="16"
+                  height="16"
+                  fill="currentColor"
+                  viewBox="0 0 16 16"
+                >
+                  <path
+                    fill-rule="evenodd"
+                    d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"
+                  />
+                </svg>
+                {{ $t('questionPage["questionDetailBackbtn"]') }}
+              </button>
+
+              <!-- <div class="feedback">
+                <span>这篇回答对您有帮助吗?</span>
+                <button class="feedback-btn yes">有帮助</button>
+                <button class="feedback-btn no">没帮助</button>
+              </div> -->
+            </div>
+
+            <div class="detail-header">
+              <h2>{{ currentQuestion.title }}</h2>
+              <div class="meta">
+                <span>{{
+                  $t('system["updateTimeTxt"]', {
+                    updateTime: formatDate(currentQuestion.updateTime, locale),
+                  })
+                }}</span>
+                <span>{{
+                  $t('questionPage["questionReadCount"]', { count: currentQuestion.views })
+                }}</span>
+              </div>
+            </div>
+
+            <div class="detail-content" v-html="currentQuestion.content"></div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 分类导航侧边抽屉 -->
+      <a-drawer
+        :open="visible"
+        :closable="false"
+        :title="$t(`questionPage['questionDrawerTitle']`)"
+        placement="right"
+        width="70%"
+        getContainer=".question-main__container-768"
+        class=""
+        @close="closeCategoryDrawer"
+      >
+        <div class="question-sidebar">
+          <div
+            v-for="category in categoryList"
+            :key="category.id"
+            class="category-item"
+            :class="{ active: activeCategory === category.id }"
+            @click="changeCategory(category.id)"
+          >
+            {{ category.name }}
+            <span class="count">{{
+              $t('questionPage["questionCategoryCountTxt"]', { count: category.count })
+            }}</span>
+          </div>
+        </div>
+      </a-drawer>
+    </section>
+
     <!-- 主要内容区 -->
-    <div class="question-main__container width-1200">
-      <!-- 左侧导航 -->
+    <div class="question-main__container question-main-normal width-1200">
+      <!-- 左侧分类导航 -->
       <div class="question-sidebar">
         <div
-          v-for="category in categories"
+          v-for="category in categoryList"
           :key="category.id"
           class="category-item"
           :class="{ active: activeCategory === category.id }"
           @click="changeCategory(category.id)"
         >
           {{ category.name }}
-          <span class="count">{{ category.count }}个问题</span>
+          <span class="count">{{
+            $t('questionPage["questionCategoryCountTxt"]', { count: category.count })
+          }}</span>
         </div>
       </div>
 
       <!-- 右侧内容 -->
       <div class="question-content">
         <template v-if="!currentQuestion">
-          <!-- 搜索结果提示 -->
+          <!-- 搜索结果列表 -->
           <div v-if="searchResults.length > 0" class="search-results">
-            <h3>搜索结果 ({{ searchResults.length }}条)</h3>
+            <h3>{{ $t('questionPage["searchResultTitle"]', { count: searchResults.length }) }}</h3>
             <div
               v-for="item in searchResults"
               :key="item.id"
@@ -67,15 +202,19 @@
             <h2>{{ getCategoryName(activeCategory) }}</h2>
 
             <div
-              v-for="question in filteredQuestions"
+              v-for="question in questionList"
               :key="question.id"
               class="question-item"
               @click="showQuestionDetail(question)"
             >
               <div class="question-title">
                 {{ question.title }}
-                <div v-if="question.isHot" class="question-tag hot-tag">热门</div>
-                <div v-if="question.isNew" class="question-tag new-tag">新</div>
+                <div v-if="question.isHot" class="question-tag hot-tag">
+                  {{ $t('questionPage["questionTagHot"]') }}
+                </div>
+                <div v-if="question.isNew" class="question-tag new-tag">
+                  {{ $t('questionPage["questionTagNew"]') }}
+                </div>
               </div>
               <div class="question-preview">{{ question.preview }}</div>
             </div>
@@ -87,8 +226,14 @@
           <div class="detail-header">
             <h2>{{ currentQuestion.title }}</h2>
             <div class="meta">
-              <span>更新于 {{ formatDate(currentQuestion.updateTime) }}</span>
-              <span>阅读 {{ currentQuestion.views }} 次</span>
+              <span>{{
+                $t('system["updateTimeTxt"]', {
+                  updateTime: formatDate(currentQuestion.updateTime, locale),
+                })
+              }}</span>
+              <span>{{
+                $t('questionPage["questionReadCount"]', { count: currentQuestion.views })
+              }}</span>
             </div>
           </div>
 
@@ -108,7 +253,7 @@
                   d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"
                 />
               </svg>
-              返回列表
+              {{ $t('questionPage["questionDetailBackbtn"]') }}
             </button>
 
             <!-- <div class="feedback">
@@ -123,8 +268,8 @@
 
     <!-- 联系客服 -->
     <div class="contact-section width-1200">
-      <h3>没有找到您需要的答案?</h3>
-      <p>我们的客服团队随时为您服务</p>
+      <h3>{{ $t('questionPage["contactTitle"]') }}</h3>
+      <p>{{ $t('questionPage["contactDesc"]') }}</p>
       <div class="contact-methods">
         <div class="contact-method">
           <svg
@@ -139,9 +284,9 @@
             />
           </svg>
           <div>
-            <strong>电话支持</strong>
+            <strong>{{ $t('questionPage["contactForPhoneTitle"]') }}</strong>
             <p>400-888-9999</p>
-            <p>周一至周日 9:00-18:00</p>
+            <p>{{ $t('questionPage["contactForPhoneWorkTime"]') }}</p>
           </div>
         </div>
 
@@ -158,28 +303,9 @@
             />
           </svg>
           <div>
-            <strong>电子邮件</strong>
+            <strong>{{ $t('questionPage["contactForEmailTitle"]') }}</strong>
             <p>support@example.com</p>
-            <p>我们会在24小时内回复</p>
-          </div>
-        </div>
-
-        <div class="contact-method">
-          <svg
-            xmlns="http://www.w3.org/2000/svg"
-            width="24"
-            height="24"
-            fill="currentColor"
-            viewBox="0 0 16 16"
-          >
-            <path
-              d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"
-            />
-          </svg>
-          <div>
-            <strong>在线客服</strong>
-            <p>点击右下角"在线咨询"</p>
-            <p>工作时间实时沟通</p>
+            <p>{{ $t('questionPage["contactForEmailWorkTime"]') }}</p>
           </div>
         </div>
       </div>
@@ -187,222 +313,46 @@
   </div>
 </template>
 
-<script setup>
-import { ref, computed } from 'vue'
-
-// 问题分类
-const categories = ref([
-  { id: 1, name: '账号问题', count: 12 },
-  { id: 2, name: '支付问题', count: 8 },
-  { id: 3, name: '订单问题', count: 15 },
-  { id: 4, name: '产品使用', count: 23 },
-  { id: 5, name: '售后服务', count: 7 },
-  { id: 6, name: '其他问题', count: 5 },
-])
-
-// 模拟问题数据
-const questions = ref([
-  {
-    id: 101,
-    categoryId: 1,
-    title: '如何注册账号?',
-    preview: '详细说明注册账号的步骤和注意事项...',
-    content: `
-      <h3>注册账号步骤</h3>
-      <ol>
-        <li>点击网站右上角的"注册"按钮</li>
-        <li>填写您的手机号码或电子邮箱</li>
-        <li>设置登录密码(6-20位字符,包含字母和数字)</li>
-        <li>输入收到的验证码</li>
-        <li>阅读并同意用户协议</li>
-        <li>点击"立即注册"完成注册</li>
-      </ol>
-      <p><strong>注意事项:</strong></p>
-      <ul>
-        <li>请使用常用手机号或邮箱,以便接收重要通知</li>
-        <li>密码请勿设置过于简单</li>
-        <li>如未收到验证码,请检查垃圾邮件或60秒后重新获取</li>
-      </ul>
-    `,
-    updateTime: '2023-05-15',
-    views: 1245,
-    isHot: true,
-    isNew: false,
-  },
-  {
-    id: 102,
-    categoryId: 1,
-    title: '忘记密码怎么办?',
-    preview: '密码找回的几种方法和步骤说明...',
-    content: `
-      <h3>找回密码方法</h3>
-      <p>如果您忘记了密码,可以通过以下方式找回:</p>
-      
-      <h4>方法一:通过手机找回</h4>
-      <ol>
-        <li>在登录页面点击"忘记密码"</li>
-        <li>选择"通过手机找回"</li>
-        <li>输入注册时使用的手机号码</li>
-        <li>获取并输入短信验证码</li>
-        <li>设置新密码并确认</li>
-      </ol>
-      
-      <h4>方法二:通过邮箱找回</h4>
-      <ol>
-        <li>在登录页面点击"忘记密码"</li>
-        <li>选择"通过邮箱找回"</li>
-        <li>输入注册时使用的邮箱地址</li>
-        <li>登录邮箱查收重置密码邮件</li>
-        <li>点击邮件中的链接设置新密码</li>
-      </ol>
-      
-      <p>如果以上方法都无法解决您的问题,请联系客服人员。</p>
-    `,
-    updateTime: '2023-06-02',
-    views: 876,
-    isHot: true,
-    isNew: false,
-  },
-  {
-    id: 201,
-    categoryId: 2,
-    title: '支持哪些支付方式?',
-    preview: '介绍平台目前支持的支付渠道...',
-    content: `
-      <h3>支持的支付方式</h3>
-      <p>我们目前支持以下支付方式:</p>
-      
-      <div class="payment-method">
-        <h4>1. 在线支付</h4>
-        <ul>
-          <li>微信支付</li>
-          <li>支付宝</li>
-          <li>银联在线支付</li>
-          <li>Apple Pay</li>
-        </ul>
-      </div>
-      
-      <div class="payment-method">
-        <h4>2. 银行卡支付</h4>
-        <p>支持以下银行的储蓄卡和信用卡:</p>
-        <ul>
-          <li>中国工商银行</li>
-          <li>中国建设银行</li>
-          <li>中国银行</li>
-          <li>招商银行</li>
-          <li>交通银行等主流银行</li>
-        </ul>
-      </div>
-      
-      <p><strong>注意:</strong>部分银行可能有支付限额,请以银行规定为准。</p>
-    `,
-    updateTime: '2023-04-28',
-    views: 1532,
-    isHot: false,
-    isNew: false,
-  },
-  {
-    id: 301,
-    categoryId: 3,
-    title: '如何查询订单状态?',
-    preview: '订单状态查询的几种途径和方法...',
-    content: `
-      <h3>查询订单状态</h3>
-      <p>您可以通过以下方式查询订单状态:</p>
-      
-      <h4>方法一:网站查询</h4>
-      <ol>
-        <li>登录您的账号</li>
-        <li>点击右上角"我的订单"</li>
-        <li>在订单列表中找到相应订单</li>
-        <li>点击"查看详情"查看订单状态</li>
-      </ol>
-      
-      <h4>方法二:手机APP查询</h4>
-      <ol>
-        <li>打开APP并登录</li>
-        <li>点击底部导航栏"我的"</li>
-        <li>选择"我的订单"</li>
-        <li>查看相应订单状态</li>
-      </ol>
-      
-      <h4>方法三:联系客服查询</h4>
-      <p>如果您无法通过以上方式查询,可以联系客服提供订单号查询。</p>
-      
-      <p><strong>常见订单状态说明:</strong></p>
-      <ul>
-        <li><span class="status waiting">待付款</span> - 订单已生成,等待支付</li>
-        <li><span class="status paid">已支付</span> - 付款成功,等待处理</li>
-        <li><span class="status shipped">已发货</span> - 商品已发出</li>
-        <li><span class="status completed">已完成</span> - 订单交易完成</li>
-        <li><span class="status cancelled">已取消</span> - 订单已取消</li>
-      </ul>
-    `,
-    updateTime: '2023-05-20',
-    views: 2104,
-    isHot: true,
-    isNew: true,
-  },
-])
-
-// 当前选中的分类ID
-const activeCategory = ref(1)
-
-// 当前查看的问题详情
-const currentQuestion = ref(null)
-
-// 搜索查询词
-const searchQuery = ref('')
-
-// 搜索结果
-const searchResults = ref([])
-
-// 获取当前分类下的问题
-const filteredQuestions = computed(() => {
-  return questions.value.filter((q) => q.categoryId === activeCategory.value)
-})
-
-// 获取分类名称
-const getCategoryName = (id) => {
-  const category = categories.value.find((c) => c.id === id)
-  return category ? category.name : '所有问题'
-}
-
-// 切换分类
-const changeCategory = (categoryId) => {
-  activeCategory.value = categoryId
-  currentQuestion.value = null
-  searchResults.value = []
+<script setup lang="ts">
+import { useI18n } from 'vue-i18n'
+import { storeToRefs } from 'pinia'
+import { ref } from 'vue'
+import useSystemStore from '@/stores/useSystemStore'
+import useData from './hooks/useData'
+
+const { t } = useI18n()
+const systemStore = useSystemStore()
+const { locale } = storeToRefs(systemStore)
+
+const {
+  categoryList,
+  activeCategory,
+  questionList,
+  currentQuestion,
+  questions,
+  searchQuery,
+  searchResults,
+  getCategoryName,
+  changeCategory,
+  showQuestionDetail,
+  searchQuestions,
+  backToList,
+} = useData()
+
+const visible = ref<boolean>(false)
+
+const showCategoryDrawer = () => {
+  visible.value = true
 }
 
-// 显示问题详情
-const showQuestionDetail = (question) => {
-  currentQuestion.value = question
-}
-
-// 返回问题列表
-const backToList = () => {
-  currentQuestion.value = null
-}
-
-// 搜索问题
-const searchQuestions = () => {
-  if (!searchQuery.value.trim()) {
-    searchResults.value = []
-    return
-  }
-
-  const query = searchQuery.value.toLowerCase()
-  searchResults.value = questions.value.filter((q) => {
-    return q.title.toLowerCase().includes(query) || q.preview.toLowerCase().includes(query)
-  })
-  currentQuestion.value = null
+const closeCategoryDrawer = () => {
+  visible.value = false
 }
 
 // 格式化日期
-const formatDate = (dateString) => {
+const formatDate = (dateString: string, lang: string) => {
   const options = { year: 'numeric', month: 'long', day: 'numeric' }
-  return new Date(dateString).toLocaleDateString('zh-CN', options)
+  return new Date(dateString).toLocaleDateString(lang, options as Object)
 }
 </script>
 
@@ -424,8 +374,6 @@ const formatDate = (dateString) => {
 
 .question-banner {
   width: 100%;
-  background: linear-gradient(135deg, #1976d2, var(--color-active));
-  background: var(--color-active);
   background: rgba(0, 0, 0, 1);
   color: white;
   padding: 40px 15px;
@@ -547,19 +495,19 @@ const formatDate = (dateString) => {
       font-size: 1.25rem;
       margin-bottom: 15px;
       margin-bottom: 0.9375rem;
-      color: #1976d2;
+      color: var(--color-active);
     }
   }
 
   .question-list {
     h2 {
-      font-size: 24px;
-      font-size: 1.5rem;
       margin-bottom: 20px;
       margin-bottom: 1.25rem;
-      padding-bottom: 10px;
-      padding-bottom: 0.625rem;
+      padding: 10px 0;
+      padding: 0.625rem 0;
       border-bottom: 1px solid #eee;
+      font-size: 24px;
+      font-size: 1.5rem;
     }
   }
 
@@ -616,14 +564,16 @@ const formatDate = (dateString) => {
       border-bottom: 1px solid #eee;
 
       h2 {
-        font-size: 24px;
-        font-size: 1.8rem;
+        font-size: 28px;
+        font-size: 1.75rem;
         margin-bottom: 10px;
         margin-bottom: 0.625rem;
+        text-align: center;
       }
 
       .meta {
         display: flex;
+        justify-content: center;
         gap: 15px;
         gap: 0.9375rem;
         color: #757575;
@@ -690,6 +640,98 @@ const formatDate = (dateString) => {
   }
 }
 
+.question-main-768 {
+  display: none;
+  padding-bottom: 0;
+}
+
+.question-main__container-768 {
+  flex-direction: column;
+  align-items: center;
+
+  .question-sidebar {
+    width: 100%;
+  }
+
+  .question-content {
+    width: 100%;
+    border-radius: 0px;
+    border-radius: 0rem;
+    padding: 0px 0;
+    padding: 0rem 0;
+    box-shadow: none;
+  }
+
+  .question-list {
+    h2 {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 8px;
+      margin-bottom: 0.5rem;
+      color: var(--color-active);
+      font-size: 18px;
+      font-size: 1.125rem;
+    }
+
+    .category-menu-btn {
+      display: flex;
+      align-items: center;
+      color: #333;
+      font-size: 16px;
+      font-size: 1rem;
+      cursor: pointer;
+    }
+
+    .category-menu-btn img {
+      width: 28px;
+      width: 1.75rem;
+      height: 28px;
+      height: 1.75rem;
+      margin-left: 6px;
+      margin-left: 0.375rem;
+    }
+  }
+
+  :deep(.ant-drawer-body) {
+    padding: 15px 12px;
+    padding: 0.9375rem 0.75rem;
+  }
+
+  .question-detail {
+    .detail-header {
+      margin-bottom: 24px;
+      margin-bottom: 1.5rem;
+      padding-bottom: 15px;
+      padding-bottom: 0.9375rem;
+      border-bottom: 1px solid #eee;
+
+      h2 {
+        padding-top: 15px;
+        padding-top: 0.9375rem;
+        margin-bottom: 4px;
+        margin-bottom: 0.25rem;
+        font-size: 24px;
+        font-size: 1.5rem;
+      }
+    }
+
+    .detail-footer {
+      margin-top: 0;
+      padding-top: 0;
+      border-bottom: 1px solid #eee;
+      border-top: 0;
+
+      .back-btn {
+        margin: 12px 0;
+        margin: 0.75rem 0;
+        color: var(--color-active);
+        background-color: rgba(0, 0, 0, 0.02125);
+      }
+    }
+  }
+}
+
 .contact-section {
   margin-top: 32px;
   margin-top: 2rem;
@@ -737,7 +779,7 @@ const formatDate = (dateString) => {
     box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
 
     svg {
-      color: #1976d2;
+      color: var(--color-active);
       margin-top: 3px;
     }
 

+ 5 - 1
src/views/Home/modules/Banners/index.vue

@@ -13,7 +13,7 @@
           $t('paragraph["连接全球优质商品,一键下单无忧,实时查看订单进程,享受便捷购物体验。"]')
         }}
       </div>
-      <div class="banners__content-btn">
+      <div class="banners__content-btn" @click="goRegister">
         <span>{{ $t('system["立即免费注册"]') }}</span>
       </div>
     </div>
@@ -22,6 +22,10 @@
 
 
 <script lang="ts" setup>
+// 注册跳转
+const goRegister = function () {
+  window.open('https://vavabuy.net/#/pages/login/register', '__blank')
+}
 </script>
 
 

+ 6 - 1
src/views/Home/modules/WrapTwo/index.vue

@@ -33,7 +33,7 @@
         </div>
       </div>
       <div class="wrap__two-foot">
-        <div class="wrap__two-btn">{{ $t('system["立即免费注册"]') }}</div>
+        <div class="wrap__two-btn" @click="goRegister">{{ $t('system["立即免费注册"]') }}</div>
       </div>
     </div>
   </section>
@@ -63,6 +63,11 @@ const stepList = reactive<IStep[]>([
     desc: '合并包裹并节省高达80%的运费',
   },
 ])
+
+// 注册跳转
+const goRegister = function () {
+  window.open('https://vavabuy.net/#/pages/login/register', '__blank')
+}
 </script>
 
 

+ 1 - 1
src/views/Layout/modules/Header/hooks/useLinkList.ts

@@ -40,7 +40,7 @@ function useLinkList() {
     },
     {
       text: '在 VAVA BUY 购物',
-      url: 'https://www.baidu.com'
+      url: 'https://vavabuy.net'
     },
   ])
 

+ 6 - 1
src/views/Layout/modules/Header/index.vue

@@ -43,7 +43,7 @@
               </a-menu>
             </template>
           </a-dropdown>
-          <div class="login-btn">
+          <div class="login-btn" @click="goLogin">
             <span>{{ $t('system["登录"]') }}</span>
           </div>
         </div>
@@ -168,6 +168,11 @@ const goHome = function () {
     path: '/',
   })
 }
+
+// 登录跳转
+const goLogin = function () {
+  window.open('https://vavabuy.net/#/pages/login/login', '__blank')
+}
 </script>
 
 

BIN
vava_buy_official.zip