2
0

2 Ревизии d1e2920698 ... 64fd225eaf

Автор SHA1 Съобщение Дата
  urban 64fd225eaf fix: 统一任务状态定义,筹备中任务在列表中可见 преди 2 седмици
  urban 270728326d feat: 主题切换与底部导航支持多语言,优化首页任务中心布局 преди 2 седмици
променени са 8 файла, в които са добавени 97 реда и са изтрити 24 реда
  1. 1 1
      src/components/headerView/index.vue
  2. 8 1
      src/locales/en.json
  3. 9 2
      src/locales/id.json
  4. 9 2
      src/locales/vi.json
  5. 12 5
      src/locales/zh.json
  6. 19 2
      src/views/hall/index.vue
  7. 25 7
      src/views/home/index.vue
  8. 14 4
      src/views/task/list.vue

+ 1 - 1
src/components/headerView/index.vue

@@ -42,7 +42,7 @@
                 @click.stop="onSelectTheme(item.key)"
               >
                 <div class="theme-dot" :class="'dot-' + item.key"></div>
-                <span>{{ item.label }}</span>
+                <span>{{ $t(item.labelKey) }}</span>
                 <span v-if="currentTheme === item.key" class="check-mark">&#10003;</span>
               </div>
             </div>

+ 8 - 1
src/locales/en.json

@@ -150,6 +150,7 @@
     "normal": "Normal",
     "hard": "Hard",
     "remaining": "Remaining",
+    "preparing": "Coming Soon",
     "claimed": "Claimed",
     "deadline": "Deadline",
     "reviewTime": "Review Time",
@@ -340,5 +341,11 @@
     "socialMedia": "Social Media",
     "contactEmail": "Contact Email",
     "contactTelegram": "Contact Telegram"
+  },
+  "theme": {
+    "title": "Theme",
+    "dark": "Dark Mode",
+    "blue": "Classic Blue",
+    "light": "Light Mode"
   }
-}
+}

+ 9 - 2
src/locales/id.json

@@ -23,7 +23,7 @@
   "tab": {
     "home": "Beranda",
     "hall": "Aula",
-    "gameShow": "Game",
+    "gameShow": "Permainan",
     "rank": "Peringkat",
     "mine": "Saya"
   },
@@ -150,6 +150,7 @@
     "normal": "Normal",
     "hard": "Sulit",
     "remaining": "Tersisa",
+    "preparing": "Segera Hadir",
     "claimed": "Diklaim",
     "deadline": "Batas waktu",
     "reviewTime": "Waktu peninjauan",
@@ -314,5 +315,11 @@
     "socialMedia": "Media sosial",
     "contactEmail": "Email kontak",
     "contactTelegram": "Telegram kontak"
+  },
+  "theme": {
+    "title": "Tema",
+    "dark": "Mode Gelap",
+    "blue": "Biru Klasik",
+    "light": "Mode Terang"
   }
-}
+}

+ 9 - 2
src/locales/vi.json

@@ -23,7 +23,7 @@
   "tab": {
     "home": "Trang chủ",
     "hall": "Đại sảnh",
-    "gameShow": "Game",
+    "gameShow": "Trò chơi",
     "rank": "Xếp hạng",
     "mine": "Tôi"
   },
@@ -150,6 +150,7 @@
     "normal": "Bình thường",
     "hard": "Khó",
     "remaining": "Còn lại",
+    "preparing": "Sắp ra mắt",
     "claimed": "Đã nhận",
     "deadline": "Thời hạn",
     "reviewTime": "Thời gian xét duyệt",
@@ -317,5 +318,11 @@
     "socialMedia": "Mạng xã hội",
     "contactEmail": "Email liên hệ",
     "contactTelegram": "Telegram liên hệ"
+  },
+  "theme": {
+    "title": "Chủ đề",
+    "dark": "Chế độ tối",
+    "blue": "Xanh cổ điển",
+    "light": "Chế độ sáng"
   }
-}
+}

+ 12 - 5
src/locales/zh.json

@@ -23,7 +23,7 @@
   "tab": {
     "home": "首页",
     "hall": "大厅",
-    "gameShow": "活动",
+    "gameShow": "游戏",
     "rank": "排行",
     "mine": "我的"
   },
@@ -84,7 +84,7 @@
     "heading": "通用条款及条件",
     "lastUpdated": "最后更新日期:2025年12月1日",
     "section1Title": "1. 接受条款",
-    "section1Content": "访问和使用 vitiens.com(\u201c本网站\u201d)即表示您同意受本条款及条件和我们的隐私政策的约束。如果您不同意,请立即停止使用本网站。",
+    "section1Content": "访问和使用 vitiens.com(“本网站”)即表示您同意受本条款及条件和我们的隐私政策的约束。如果您不同意,请立即停止使用本网站。",
     "section2Title": "2. 网站使用",
     "section2Intro": "禁止行为:用户同意不将本网站用于任何非法目的,包括但不限于:",
     "section2Item1": "传播病毒或恶意代码。",
@@ -98,7 +98,7 @@
     "section4Item2": "您须对您账户下发生的所有活动负责。",
     "section4Item3": "我们保留终止违反本条款的账户的权利。",
     "section5Title": "5. 责任限制",
-    "section5Content": "在法律允许的最大范围内,Vitiens Group 对您使用本网站而引起的任何间接、附带或后果性损害概不负责。本网站按\u201c现状\u201d和\u201c现有\u201d基础提供,不提供任何形式的保证。",
+    "section5Content": "在法律允许的最大范围内,Vitiens Group 对您使用本网站而引起的任何间接、附带或后果性损害概不负责。本网站按“现状”和“现有”基础提供,不提供任何形式的保证。",
     "section6Title": "6. 外部链接",
     "section6Content": "本网站可能包含指向第三方网站的链接。我们不认可或承担任何第三方网站的内容、隐私政策或做法的责任。",
     "section7Title": "7. 条款变更",
@@ -118,7 +118,7 @@
     "section3Title": "3. 我们会分享您的数据吗?",
     "section3Content": "不会,我们不会出售您的数据。我们仅与维持网站运行的工具(例如我们的电子邮件服务提供商或网站托管商)共享您的数据。他们也必须对您的信息保密。",
     "section4Title": "4. 您的选择",
-    "section4Item1": "电子邮件:您可以点击我们发送的任何电子邮件中的\u201c取消订阅\u201d链接来停止接收邮件。",
+    "section4Item1": "电子邮件:您可以点击我们发送的任何电子邮件中的“取消订阅”链接来停止接收邮件。",
     "section4Item2": "Cookie:您可以在浏览器设置中禁用 Cookie,但禁用后网站的某些功能可能无法正常使用。",
     "section4Item3": "删除:想要我们删除您的信息?只需发送电子邮件至 parker1{'@'}kbcsvn.com,我们将为您处理。",
     "section5Title": "5. 安全",
@@ -150,6 +150,7 @@
     "normal": "普通",
     "hard": "困难",
     "remaining": "剩余数量",
+    "preparing": "筹备中",
     "claimed": "已领取",
     "deadline": "截止时间",
     "reviewTime": "审核时间",
@@ -340,5 +341,11 @@
     "socialMedia": "社交媒体",
     "contactEmail": "联系邮箱",
     "contactTelegram": "联系Telegram"
+  },
+  "theme": {
+    "title": "主题",
+    "dark": "暗黑模式",
+    "blue": "蓝白经典",
+    "light": "浅色护眼"
   }
-}
+}

+ 19 - 2
src/views/hall/index.vue

@@ -33,9 +33,10 @@
       <div class="task-list">
         <div
           class="task-card"
+          :class="{ 'task-preparing': task.status === 0 }"
           v-for="task in taskList"
           :key="task.id"
-          @click="goTaskDetail(task.id)"
+          @click="task.status !== 0 && goTaskDetail(task.id)"
         >
           <div class="task-content">
             <div class="task-cover" v-if="task.cover">
@@ -45,7 +46,8 @@
               <div class="task-title">{{ task.title }}</div>
               <div class="task-footer">
                 <span class="price">+{{ formatReward(task.rewardAmount ?? task.price) }}</span>
-                <span class="remaining">{{ $t('task.remaining') }}: {{ task.remainCount ?? (task.maxNum - task.applyNum) }}</span>
+                <span class="remaining" v-if="task.status !== 0">{{ $t('task.remaining') }}: {{ task.remainCount ?? (task.maxNum - task.applyNum) }}</span>
+                <span class="preparing-tag" v-else>{{ $t('task.preparing') }}</span>
               </div>
             </div>
           </div>
@@ -315,9 +317,24 @@ onMounted(() => {
             font-size: min(2.933vw, 14px);
             color: var(--text-secondary, rgba(255, 255, 255, 0.5));
           }
+
+          .preparing-tag {
+            display: inline-block;
+            padding: 1px 8px;
+            background: rgba(255, 152, 0, 0.2);
+            color: #ff9800;
+            border-radius: 8px;
+            font-size: min(2.8vw, 12px);
+          }
         }
       }
     }
+
+    &.task-preparing {
+      opacity: 0.45;
+      cursor: not-allowed;
+      filter: grayscale(0.3);
+    }
   }
 }
 </style>

+ 25 - 7
src/views/home/index.vue

@@ -56,9 +56,10 @@
         <div class="task-list">
           <div
             class="task-card"
+            :class="{ 'task-preparing': task.status === 0 }"
             v-for="task in taskList"
             :key="task.id"
-            @click="goTaskDetail(task.id)"
+            @click="task.status !== 0 && goTaskDetail(task.id)"
           >
             <div class="task-icon">
               <img :src="task.cover || task.categoryIcon || defaultIcon" alt="" />
@@ -66,7 +67,8 @@
             <div class="task-info">
               <div class="task-title">{{ task.title }}</div>
               <div class="task-meta">
-                <span class="remaining">{{ $t('task.remaining') }}: {{ task.remainCount ?? (task.maxNum - task.applyNum) }}</span>
+                <span class="remaining" v-if="task.status !== 0">{{ $t('task.remaining') }}: {{ task.remainCount ?? (task.maxNum - task.applyNum) }}</span>
+                <span class="preparing-tag" v-else>{{ $t('task.preparing') }}</span>
               </div>
             </div>
             <div class="task-price">
@@ -268,23 +270,23 @@ onMounted(() => {
     display: flex;
     justify-content: space-between;
     align-items: center;
-    margin-bottom: min(3.2vw, 15.36px);
+    margin-bottom: min(2.667vw, 12px);
 
     .title {
-      font-size: min(4.267vw, 20.48px);
+      font-size: min(3.467vw, 15px);
       font-weight: 600;
       color: var(--text-primary, #fff);
     }
 
     .tabs {
       display: flex;
-      gap: min(3.2vw, 15.36px);
+      gap: min(2.667vw, 12px);
 
       .tab-item {
-        font-size: min(3.733vw, 17.92px);
+        font-size: min(3.2vw, 13px);
         color: var(--color-tab-inactive, rgba(255, 255, 255, 0.5));
         cursor: pointer;
-        padding-bottom: min(1.067vw, 5.12px);
+        padding-bottom: min(0.8vw, 3px);
 
         &.active {
           color: var(--color-tab-active, #ffc300);
@@ -353,6 +355,22 @@ onMounted(() => {
         color: var(--text-secondary, rgba(255, 255, 255, 0.5));
       }
     }
+
+    &.task-preparing {
+      opacity: 0.45;
+      cursor: not-allowed;
+      position: relative;
+      filter: grayscale(0.3);
+
+      .preparing-tag {
+        display: inline-block;
+        padding: 1px 8px;
+        background: rgba(255, 152, 0, 0.2);
+        color: #ff9800;
+        border-radius: 8px;
+        font-size: min(2.8vw, 12px);
+      }
+    }
   }
 
   .loading-view {

+ 14 - 4
src/views/task/list.vue

@@ -49,21 +49,22 @@
         >
           <div
             class="task-card"
+            :class="{ 'task-preparing': task.status === 0 }"
             v-for="task in taskList"
             :key="task.id"
-            @click="goDetail(task.id)"
+            @click="task.status !== 0 && goDetail(task.id)"
           >
             <div class="task-img">
               <img :src="task.cover || task.imageMaterial?.[0] || defaultIcon" />
-              <div class="task-tag" :class="getDifficultyClass(task.difficulty)">
-                {{ getDifficultyText(task.difficulty) }}
+              <div class="task-tag" :class="task.status === 0 ? 'preparing' : getDifficultyClass(task.difficulty)">
+                {{ task.status === 0 ? $t('task.preparing') : getDifficultyText(task.difficulty) }}
               </div>
             </div>
             <div class="task-info">
               <div class="task-title">{{ task.title }}</div>
               <div class="task-meta">
                 <span class="remaining">
-                  {{ $t('task.remaining') }}: {{ task.remainCount ?? task.remaining ?? 0 }}
+                  {{ task.status === 0 ? $t('task.preparing') : `${$t('task.remaining')}: ${task.remainCount ?? task.remaining ?? 0}` }}
                 </span>
               </div>
               <div class="task-price">+{{ formatReward(task.rewardAmount ?? task.price) }} USDT</div>
@@ -351,6 +352,9 @@ onMounted(() => {
       &.hard {
         background: #f44336;
       }
+      &.preparing {
+        background: rgba(255, 152, 0, 0.8);
+      }
     }
   }
 
@@ -384,5 +388,11 @@ onMounted(() => {
       color: var(--color-accent-light, #ffc300);
     }
   }
+
+  &.task-preparing {
+    opacity: 0.45;
+    cursor: not-allowed;
+    filter: grayscale(0.3);
+  }
 }
 </style>