修改部分页面
This commit is contained in:
@@ -7,7 +7,7 @@ const routes = [
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'Home',
|
name: 'Home',
|
||||||
redirect: '/transfers',
|
redirect: '/mainpage',
|
||||||
meta: {
|
meta: {
|
||||||
title: '首页'
|
title: '首页'
|
||||||
}
|
}
|
||||||
@@ -80,14 +80,6 @@ const routes = [
|
|||||||
requiresAuth: true
|
requiresAuth: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/home',
|
|
||||||
name: 'HomePage',
|
|
||||||
component: () => import('@/views/Home.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '首页'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/shop',
|
path: '/shop',
|
||||||
name: 'Shop',
|
name: 'Shop',
|
||||||
@@ -131,15 +123,6 @@ const routes = [
|
|||||||
requiresAuth: true
|
requiresAuth: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/task-center',
|
|
||||||
name: 'TaskCenter',
|
|
||||||
component: () => import('@/views/TaskCenter.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '任务中心',
|
|
||||||
requiresAuth: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/transfers',
|
path: '/transfers',
|
||||||
name: 'Transfers',
|
name: 'Transfers',
|
||||||
@@ -186,14 +169,6 @@ const routes = [
|
|||||||
isAgent: true
|
isAgent: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/about',
|
|
||||||
name: 'About',
|
|
||||||
component: () => import('@/views/About.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '关于我们'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/customerservice',
|
path: '/customerservice',
|
||||||
name: 'CustomerService',
|
name: 'CustomerService',
|
||||||
|
|||||||
@@ -1,453 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="about-page">
|
|
||||||
<!-- 导航栏 -->
|
|
||||||
<nav class="navbar">
|
|
||||||
<div class="nav-left">
|
|
||||||
<el-button
|
|
||||||
type="text"
|
|
||||||
@click="$router.go(-1)"
|
|
||||||
class="back-btn"
|
|
||||||
>
|
|
||||||
<el-icon><ArrowLeft /></el-icon>
|
|
||||||
返回
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="nav-center">
|
|
||||||
<h1 class="nav-title">关于我们</h1>
|
|
||||||
</div>
|
|
||||||
<div class="nav-right"></div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- 页面内容 -->
|
|
||||||
<div class="about-content">
|
|
||||||
<!-- 网站介绍 -->
|
|
||||||
<section class="intro-section">
|
|
||||||
<div class="intro-header">
|
|
||||||
<div class="logo">
|
|
||||||
<el-icon size="60"><Platform /></el-icon>
|
|
||||||
</div>
|
|
||||||
<h2>融互通</h2>
|
|
||||||
<p class="tagline">专业的积分兑换与商品管理平台</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="intro-content">
|
|
||||||
<p>
|
|
||||||
积分商城系统是一个现代化的积分兑换与商品管理平台,致力于为用户提供丰富的商品选择和便捷的积分兑换体验。
|
|
||||||
我们相信积分的价值在于为用户带来实际的收益和满足感,通过技术的力量让积分兑换变得更加简单高效。
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- 功能特色 -->
|
|
||||||
<section class="features-section">
|
|
||||||
<h3>功能特色</h3>
|
|
||||||
<div class="features-grid">
|
|
||||||
<div class="feature-item">
|
|
||||||
<div class="feature-icon">
|
|
||||||
<el-icon><ShoppingBag /></el-icon>
|
|
||||||
</div>
|
|
||||||
<h4>丰富商品</h4>
|
|
||||||
<p>精选优质商品,涵盖生活用品、数码产品、虚拟服务等多个品类</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="feature-item">
|
|
||||||
<div class="feature-icon">
|
|
||||||
<el-icon><Coin /></el-icon>
|
|
||||||
</div>
|
|
||||||
<h4>积分兑换</h4>
|
|
||||||
<p>灵活的积分兑换机制,让您的积分发挥最大价值,享受购物乐趣</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="feature-item">
|
|
||||||
<div class="feature-icon">
|
|
||||||
<el-icon><TrendCharts /></el-icon>
|
|
||||||
</div>
|
|
||||||
<h4>积分管理</h4>
|
|
||||||
<p>完整的积分获取和消费记录,让您清楚了解每一分积分的来源和去向</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="feature-item">
|
|
||||||
<div class="feature-icon">
|
|
||||||
<el-icon><User /></el-icon>
|
|
||||||
</div>
|
|
||||||
<h4>个人中心</h4>
|
|
||||||
<p>完善的个人资料管理,记录您的兑换历程和积分成长轨迹</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- 技术栈 -->
|
|
||||||
<section class="tech-section">
|
|
||||||
<h3>技术栈</h3>
|
|
||||||
<div class="tech-grid">
|
|
||||||
<div class="tech-category">
|
|
||||||
<h4>前端技术</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Vue 3 + Composition API</li>
|
|
||||||
<li>Element Plus UI 组件库</li>
|
|
||||||
<li>Vue Router 路由管理</li>
|
|
||||||
<li>Pinia 状态管理</li>
|
|
||||||
<li>Vite 构建工具</li>
|
|
||||||
<li>响应式设计</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="tech-category">
|
|
||||||
<h4>后端技术</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Node.js + Express</li>
|
|
||||||
<li>MySQL 数据库</li>
|
|
||||||
<li>JWT 身份认证</li>
|
|
||||||
<li>RESTful API 设计</li>
|
|
||||||
<li>积分系统管理</li>
|
|
||||||
<li>订单处理系统</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- 联系我们 -->
|
|
||||||
<section class="contact-section">
|
|
||||||
<h3>联系我们</h3>
|
|
||||||
<div class="contact-info">
|
|
||||||
<div class="contact-item">
|
|
||||||
<el-icon><Message /></el-icon>
|
|
||||||
<div>
|
|
||||||
<h4>邮箱</h4>
|
|
||||||
<p>contact@example.com</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="contact-item">
|
|
||||||
<el-icon><Phone /></el-icon>
|
|
||||||
<div>
|
|
||||||
<h4>电话</h4>
|
|
||||||
<p>400-123-4567</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="contact-item">
|
|
||||||
<el-icon><Location /></el-icon>
|
|
||||||
<div>
|
|
||||||
<h4>地址</h4>
|
|
||||||
<p>北京市朝阳区科技园区</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- 版本信息 -->
|
|
||||||
<section class="version-section">
|
|
||||||
<div class="version-info">
|
|
||||||
<p><strong>版本:</strong>v1.0.0</p>
|
|
||||||
<p><strong>更新时间:</strong>{{ updateTime }}</p>
|
|
||||||
<p><strong>开发团队:</strong>积分商城系统开发团队</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 页脚 -->
|
|
||||||
<footer class="about-footer">
|
|
||||||
<p>© 2024 积分商城系统. All rights reserved.</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import {
|
|
||||||
ArrowLeft,
|
|
||||||
Platform,
|
|
||||||
ShoppingBag,
|
|
||||||
Coin,
|
|
||||||
TrendCharts,
|
|
||||||
User,
|
|
||||||
Message,
|
|
||||||
Phone,
|
|
||||||
Location
|
|
||||||
} from '@element-plus/icons-vue'
|
|
||||||
|
|
||||||
// 响应式数据
|
|
||||||
const updateTime = ref('2024-01-15')
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.about-page {
|
|
||||||
min-height: 100vh;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 0 16px;
|
|
||||||
height: 56px;
|
|
||||||
background: white;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-left,
|
|
||||||
.nav-right {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-btn {
|
|
||||||
color: #409eff;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-title {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.about-content {
|
|
||||||
padding: 20px 16px;
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.intro-section {
|
|
||||||
background: white;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 40px 30px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
text-align: center;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.intro-header {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
color: #409eff;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.intro-header h2 {
|
|
||||||
margin: 0 0 8px 0;
|
|
||||||
font-size: 28px;
|
|
||||||
color: #333;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tagline {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.intro-content p {
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.8;
|
|
||||||
color: #555;
|
|
||||||
text-align: left;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-section,
|
|
||||||
.tech-section,
|
|
||||||
.contact-section {
|
|
||||||
background: white;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 30px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-section h3,
|
|
||||||
.tech-section h3,
|
|
||||||
.contact-section h3 {
|
|
||||||
margin: 0 0 24px 0;
|
|
||||||
font-size: 20px;
|
|
||||||
color: #333;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
||||||
gap: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-item {
|
|
||||||
text-align: center;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: #f8f9fa;
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-item:hover {
|
|
||||||
transform: translateY(-4px);
|
|
||||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-icon {
|
|
||||||
color: #409eff;
|
|
||||||
font-size: 32px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-item h4 {
|
|
||||||
margin: 0 0 8px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #333;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-item p {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #666;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tech-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
||||||
gap: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tech-category h4 {
|
|
||||||
margin: 0 0 16px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #333;
|
|
||||||
font-weight: 500;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
border-bottom: 2px solid #409eff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tech-category ul {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tech-category li {
|
|
||||||
padding: 8px 0;
|
|
||||||
color: #555;
|
|
||||||
font-size: 14px;
|
|
||||||
position: relative;
|
|
||||||
padding-left: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tech-category li::before {
|
|
||||||
content: '•';
|
|
||||||
color: #409eff;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-info {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
||||||
gap: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
padding: 16px;
|
|
||||||
background: #f8f9fa;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item .el-icon {
|
|
||||||
color: #409eff;
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item h4 {
|
|
||||||
margin: 0 0 4px 0;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #333;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-item p {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.version-section {
|
|
||||||
background: white;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 20px 30px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.version-info p {
|
|
||||||
margin: 8px 0;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.about-footer {
|
|
||||||
text-align: center;
|
|
||||||
padding: 20px;
|
|
||||||
color: #999;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 响应式设计 */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.about-content {
|
|
||||||
padding: 15px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.intro-section,
|
|
||||||
.features-section,
|
|
||||||
.tech-section,
|
|
||||||
.contact-section {
|
|
||||||
padding: 20px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.intro-header h2 {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tech-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-info {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
|
||||||
.intro-section,
|
|
||||||
.features-section,
|
|
||||||
.tech-section,
|
|
||||||
.contact-section,
|
|
||||||
.version-section {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.intro-header h2 {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-section h3,
|
|
||||||
.tech-section h3,
|
|
||||||
.contact-section h3 {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -320,7 +320,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
background: #ff6b35;
|
background: #72c9ff;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -1,381 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="home">
|
|
||||||
<!-- 导航栏 -->
|
|
||||||
<el-header class="header">
|
|
||||||
<div class="header-content">
|
|
||||||
<div class="logo">
|
|
||||||
<h2>前端H5系统</h2>
|
|
||||||
</div>
|
|
||||||
<div class="nav-menu">
|
|
||||||
<el-menu
|
|
||||||
mode="horizontal"
|
|
||||||
:default-active="activeIndex"
|
|
||||||
class="nav-menu-items"
|
|
||||||
@select="handleMenuSelect"
|
|
||||||
>
|
|
||||||
<el-menu-item index="home">首页</el-menu-item>
|
|
||||||
<el-menu-item index="shop">积分商城</el-menu-item>
|
|
||||||
<el-menu-item index="about">关于</el-menu-item>
|
|
||||||
</el-menu>
|
|
||||||
</div>
|
|
||||||
<div class="user-actions">
|
|
||||||
<template v-if="userStore.isAuthenticated">
|
|
||||||
<el-dropdown @command="handleUserCommand">
|
|
||||||
<span class="user-info">
|
|
||||||
<div class="user-avatar">
|
|
||||||
{{ userStore.user?.username?.charAt(0)?.toUpperCase() }}
|
|
||||||
</div>
|
|
||||||
<span class="username">{{ userStore.user?.username }}</span>
|
|
||||||
<el-icon><ArrowDown /></el-icon>
|
|
||||||
</span>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item command="profile">个人中心</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="orders">我的订单</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="points-history">积分记录</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="transfers">货款管理</el-dropdown-item>
|
|
||||||
<el-dropdown-item divided command="logout">退出登录</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<!-- 移除登录注册按钮 -->
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
|
|
||||||
<!-- 主要内容 -->
|
|
||||||
<el-main class="main-content">
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 主要内容区域 -->
|
|
||||||
<div class="main-section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="welcome-content">
|
|
||||||
<h2 class="welcome-title">欢迎使用前端H5系统</h2>
|
|
||||||
<p class="welcome-description">您的智能管理助手</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 统计信息 -->
|
|
||||||
<div class="stats-section" v-if="userStore.isAuthenticated">
|
|
||||||
<div class="container">
|
|
||||||
<h2 class="section-title">系统概览</h2>
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :xs="12" :sm="6" v-for="stat in stats" :key="stat.key">
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<el-icon :size="32"><component :is="stat.icon" /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="stat-content">
|
|
||||||
<div class="stat-value">{{ stat.value }}</div>
|
|
||||||
<div class="stat-label">{{ stat.label }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-main>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 页脚 -->
|
|
||||||
<el-footer class="footer">
|
|
||||||
<div class="container">
|
|
||||||
<p>© 2024 前端H5系统. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</el-footer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, onMounted, computed } from 'vue'
|
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
import { useUserStore } from '@/stores/user'
|
|
||||||
|
|
||||||
import { ArrowDown, User, View, Clock, Document, Edit, Setting, DataAnalysis, Star } from '@element-plus/icons-vue'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const userStore = useUserStore()
|
|
||||||
|
|
||||||
// 响应式数据
|
|
||||||
const activeIndex = ref('home')
|
|
||||||
const stats = ref([
|
|
||||||
{ key: 'users', label: '用户数量', value: 0, icon: 'User' },
|
|
||||||
{ key: 'orders', label: '订单总数', value: 0, icon: 'Document' },
|
|
||||||
{ key: 'products', label: '商品数量', value: 0, icon: 'Star' },
|
|
||||||
{ key: 'transfers', label: '转账记录', value: 0, icon: 'Clock' }
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 方法
|
|
||||||
const handleMenuSelect = (index) => {
|
|
||||||
activeIndex.value = index
|
|
||||||
switch (index) {
|
|
||||||
case 'home':
|
|
||||||
router.push('/transfers')
|
|
||||||
break
|
|
||||||
case 'shop':
|
|
||||||
router.push('/shop')
|
|
||||||
break
|
|
||||||
case 'about':
|
|
||||||
router.push('/about')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleUserCommand = (command) => {
|
|
||||||
switch (command) {
|
|
||||||
case 'profile':
|
|
||||||
router.push('/profile')
|
|
||||||
break
|
|
||||||
case 'orders':
|
|
||||||
router.push('/orders')
|
|
||||||
break
|
|
||||||
case 'points-history':
|
|
||||||
router.push('/points-history')
|
|
||||||
break
|
|
||||||
case 'transfers':
|
|
||||||
router.push('/transfers')
|
|
||||||
break
|
|
||||||
case 'logout':
|
|
||||||
userStore.logout()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 获取统计数据
|
|
||||||
const fetchStats = async () => {
|
|
||||||
try {
|
|
||||||
// 这里可以调用相关API获取统计数据
|
|
||||||
// 暂时使用模拟数据
|
|
||||||
stats.value = [
|
|
||||||
{ key: 'users', label: '用户数量', value: 156, icon: 'User' },
|
|
||||||
{ key: 'orders', label: '订单总数', value: 89, icon: 'Document' },
|
|
||||||
{ key: 'products', label: '商品数量', value: 45, icon: 'Star' },
|
|
||||||
{ key: 'transfers', label: '转账记录', value: 23, icon: 'Clock' }
|
|
||||||
]
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取统计数据失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生命周期
|
|
||||||
onMounted(() => {
|
|
||||||
if (userStore.isAuthenticated) {
|
|
||||||
fetchStats()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.home {
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
|
|
||||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo h2 {
|
|
||||||
color: white;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu-items {
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu-items .el-menu-item {
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu-items .el-menu-item:hover,
|
|
||||||
.nav-menu-items .el-menu-item.is-active {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-info {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-avatar {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
flex: 1;
|
|
||||||
padding: 0 0 80px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.container {
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-section,
|
|
||||||
.stats-section {
|
|
||||||
padding: 60px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-section {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
min-height: 50vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 32px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
color: #303133;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-content {
|
|
||||||
text-align: center;
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 40px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-title {
|
|
||||||
font-size: 32px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
color: #303133;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-description {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #606266;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.stat-card {
|
|
||||||
background: white;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 20px;
|
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 15px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-icon {
|
|
||||||
color: #409eff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-value {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #303133;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-label {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #909399;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
background-color: #303133;
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .container {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.header-content {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 15px;
|
|
||||||
padding: 15px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu {
|
|
||||||
order: 3;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-actions {
|
|
||||||
order: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-title {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
padding-bottom: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -249,9 +249,9 @@ export default {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
max-width: 375px;
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 欢迎文字 */
|
/* 欢迎文字 */
|
||||||
@@ -267,7 +267,8 @@ export default {
|
|||||||
|
|
||||||
/* 轮播图样式 */
|
/* 轮播图样式 */
|
||||||
.carousel {
|
.carousel {
|
||||||
width: 343px;
|
width: 100%;
|
||||||
|
max-width: 343px;
|
||||||
height: 148px;
|
height: 148px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -299,7 +300,8 @@ export default {
|
|||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between; /* 保持元素均匀分布 */
|
justify-content: space-between; /* 保持元素均匀分布 */
|
||||||
width: 343px;
|
width: 100%;
|
||||||
|
max-width: 343px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
padding: 0; /* 移除内边距 */
|
padding: 0; /* 移除内边距 */
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@@ -339,7 +341,8 @@ export default {
|
|||||||
|
|
||||||
/* 操作区域样式 */
|
/* 操作区域样式 */
|
||||||
.action-area {
|
.action-area {
|
||||||
width: 343px;
|
width: 100%;
|
||||||
|
max-width: 343px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +397,8 @@ export default {
|
|||||||
|
|
||||||
/* 热门资讯 */
|
/* 热门资讯 */
|
||||||
.hot-news {
|
.hot-news {
|
||||||
width: 343px;
|
width: 100%;
|
||||||
|
max-width: 343px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ const handleLogin = async () => {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
// 登录成功,跳转到目标页面或转账管理
|
// 登录成功,跳转到目标页面或转账管理
|
||||||
const redirectPath = route.query.redirect || '/transfers'
|
const redirectPath = route.query.redirect || '/mainpage'
|
||||||
router.push(redirectPath)
|
router.push(redirectPath)
|
||||||
} else if (result.needPayment) {
|
} else if (result.needPayment) {
|
||||||
// 用户需要支付激活,直接跳转到支付页面
|
// 用户需要支付激活,直接跳转到支付页面
|
||||||
|
|||||||
@@ -1,645 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="task-center">
|
|
||||||
<!-- 导航栏 -->
|
|
||||||
<nav class="navbar">
|
|
||||||
<div class="nav-left">
|
|
||||||
<el-button
|
|
||||||
type="text"
|
|
||||||
@click="$router.go(-1)"
|
|
||||||
class="back-btn"
|
|
||||||
>
|
|
||||||
<el-icon><ArrowLeft /></el-icon>
|
|
||||||
返回
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="nav-center">
|
|
||||||
<h1 class="nav-title">任务中心</h1>
|
|
||||||
</div>
|
|
||||||
<div class="nav-right">
|
|
||||||
<el-button
|
|
||||||
type="text"
|
|
||||||
@click="$router.push('/points-history')"
|
|
||||||
class="points-btn"
|
|
||||||
>
|
|
||||||
<el-icon><Coin /></el-icon>
|
|
||||||
{{ userPoints }}
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- 任务统计 -->
|
|
||||||
<div class="task-stats">
|
|
||||||
<div class="stats-card">
|
|
||||||
<div class="stat-item">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<el-icon><Trophy /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="stat-info">
|
|
||||||
<div class="stat-value">{{ completedTasks }}</div>
|
|
||||||
<div class="stat-label">已完成</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-item">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<el-icon><Clock /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="stat-info">
|
|
||||||
<div class="stat-value">{{ pendingTasks }}</div>
|
|
||||||
<div class="stat-label">进行中</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-item">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<el-icon><Star /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="stat-info">
|
|
||||||
<div class="stat-value">{{ totalRewards }}</div>
|
|
||||||
<div class="stat-label">总积分</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 任务分类 -->
|
|
||||||
<div class="task-categories">
|
|
||||||
<div class="category-tabs">
|
|
||||||
<div
|
|
||||||
v-for="category in categories"
|
|
||||||
:key="category.key"
|
|
||||||
:class="['category-tab', { active: activeCategory === category.key }]"
|
|
||||||
@click="activeCategory = category.key"
|
|
||||||
>
|
|
||||||
<el-icon>{{ category.icon }}</el-icon>
|
|
||||||
<span>{{ category.name }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 任务列表 -->
|
|
||||||
<div class="task-list">
|
|
||||||
<div
|
|
||||||
v-for="task in filteredTasks"
|
|
||||||
:key="task.id"
|
|
||||||
:class="['task-item', {
|
|
||||||
completed: task.status === 'completed',
|
|
||||||
claimed: task.status === 'claimed'
|
|
||||||
}]"
|
|
||||||
>
|
|
||||||
<div class="task-icon">
|
|
||||||
<el-icon :size="24">{{ getTaskIcon(task.type) }}</el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="task-content">
|
|
||||||
<div class="task-title">{{ task.title }}</div>
|
|
||||||
<div class="task-desc">{{ task.description }}</div>
|
|
||||||
<div class="task-progress" v-if="task.progress !== undefined">
|
|
||||||
<el-progress
|
|
||||||
:percentage="(task.progress / task.target) * 100"
|
|
||||||
:show-text="false"
|
|
||||||
:stroke-width="4"
|
|
||||||
/>
|
|
||||||
<span class="progress-text">{{ task.progress }}/{{ task.target }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="task-reward">
|
|
||||||
<div class="reward-points">+{{ task.points }}</div>
|
|
||||||
<el-button
|
|
||||||
v-if="task.status === 'pending'"
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
@click="doTask(task)"
|
|
||||||
:loading="task.loading"
|
|
||||||
>
|
|
||||||
{{ getTaskButtonText(task) }}
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-else-if="task.status === 'completed'"
|
|
||||||
type="success"
|
|
||||||
size="small"
|
|
||||||
@click="claimReward(task)"
|
|
||||||
:loading="task.loading"
|
|
||||||
>
|
|
||||||
领取奖励
|
|
||||||
</el-button>
|
|
||||||
<el-tag
|
|
||||||
v-else-if="task.status === 'claimed'"
|
|
||||||
type="success"
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
已领取
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 空状态 -->
|
|
||||||
<div v-if="filteredTasks.length === 0" class="empty-state">
|
|
||||||
<el-icon :size="60" color="#c0c4cc"><DocumentRemove /></el-icon>
|
|
||||||
<p>暂无任务</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, computed, onMounted } from 'vue'
|
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
import { useUserStore } from '@/stores/user'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import {
|
|
||||||
ArrowLeft,
|
|
||||||
Coin,
|
|
||||||
Trophy,
|
|
||||||
Clock,
|
|
||||||
Star,
|
|
||||||
Calendar,
|
|
||||||
ShoppingCart,
|
|
||||||
Share,
|
|
||||||
User,
|
|
||||||
CreditCard,
|
|
||||||
Present,
|
|
||||||
DocumentRemove
|
|
||||||
} from '@element-plus/icons-vue'
|
|
||||||
import api from '@/utils/api'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const userStore = useUserStore()
|
|
||||||
|
|
||||||
// 响应式数据
|
|
||||||
const userPoints = ref(0)
|
|
||||||
const activeCategory = ref('daily')
|
|
||||||
const tasks = ref([])
|
|
||||||
const loading = ref(false)
|
|
||||||
|
|
||||||
// 任务分类
|
|
||||||
const categories = ref([
|
|
||||||
{ key: 'daily', name: '每日任务', icon: Calendar },
|
|
||||||
{ key: 'shopping', name: '购物任务', icon: ShoppingCart },
|
|
||||||
{ key: 'social', name: '社交任务', icon: Share },
|
|
||||||
{ key: 'profile', name: '完善资料', icon: User },
|
|
||||||
{ key: 'special', name: '特殊任务', icon: Present }
|
|
||||||
])
|
|
||||||
|
|
||||||
// 计算属性
|
|
||||||
const filteredTasks = computed(() => {
|
|
||||||
return tasks.value.filter(task => task.category === activeCategory.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
const completedTasks = computed(() => {
|
|
||||||
return tasks.value.filter(task => task.status === 'claimed').length
|
|
||||||
})
|
|
||||||
|
|
||||||
const pendingTasks = computed(() => {
|
|
||||||
return tasks.value.filter(task => task.status === 'pending' || task.status === 'completed').length
|
|
||||||
})
|
|
||||||
|
|
||||||
const totalRewards = computed(() => {
|
|
||||||
return tasks.value
|
|
||||||
.filter(task => task.status === 'claimed')
|
|
||||||
.reduce((total, task) => total + task.points, 0)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 方法
|
|
||||||
/**
|
|
||||||
* 获取任务图标
|
|
||||||
*/
|
|
||||||
const getTaskIcon = (type) => {
|
|
||||||
const iconMap = {
|
|
||||||
purchase: ShoppingCart,
|
|
||||||
share: Share,
|
|
||||||
profile: User,
|
|
||||||
transfer: CreditCard,
|
|
||||||
invite: User,
|
|
||||||
review: Star
|
|
||||||
}
|
|
||||||
return iconMap[type] || Present
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取任务按钮文本
|
|
||||||
*/
|
|
||||||
const getTaskButtonText = (task) => {
|
|
||||||
const textMap = {
|
|
||||||
purchase: '去购买',
|
|
||||||
share: '去分享',
|
|
||||||
profile: '去完善',
|
|
||||||
transfer: '去转账',
|
|
||||||
invite: '去邀请',
|
|
||||||
review: '去评价'
|
|
||||||
}
|
|
||||||
return textMap[task.type] || '去完成'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行任务
|
|
||||||
*/
|
|
||||||
const doTask = async (task) => {
|
|
||||||
task.loading = true
|
|
||||||
|
|
||||||
try {
|
|
||||||
switch (task.type) {
|
|
||||||
case 'purchase':
|
|
||||||
router.push('/shop')
|
|
||||||
break
|
|
||||||
case 'share':
|
|
||||||
await shareApp()
|
|
||||||
break
|
|
||||||
case 'profile':
|
|
||||||
router.push('/profile')
|
|
||||||
break
|
|
||||||
case 'transfer':
|
|
||||||
router.push('/transfers')
|
|
||||||
break
|
|
||||||
case 'invite':
|
|
||||||
await showInviteDialog()
|
|
||||||
break
|
|
||||||
case 'review':
|
|
||||||
router.push('/orders')
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
// 直接完成任务
|
|
||||||
await completeTask(task.id)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
ElMessage.error('操作失败,请重试')
|
|
||||||
} finally {
|
|
||||||
task.loading = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分享应用
|
|
||||||
*/
|
|
||||||
const shareApp = async () => {
|
|
||||||
if (navigator.share) {
|
|
||||||
try {
|
|
||||||
await navigator.share({
|
|
||||||
title: '融互通 - 资金互助平台',
|
|
||||||
text: '发现一个很棒的资金互助平台,快来看看吧!',
|
|
||||||
url: window.location.origin
|
|
||||||
})
|
|
||||||
|
|
||||||
// 完成分享任务
|
|
||||||
await completeTask('share_app')
|
|
||||||
ElMessage.success('分享成功!')
|
|
||||||
} catch (error) {
|
|
||||||
if (error.name !== 'AbortError') {
|
|
||||||
ElMessage.error('分享失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 复制链接到剪贴板
|
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(window.location.origin)
|
|
||||||
await completeTask('share_app')
|
|
||||||
ElMessage.success('链接已复制到剪贴板!')
|
|
||||||
} catch (error) {
|
|
||||||
ElMessage.error('复制失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示邀请对话框
|
|
||||||
*/
|
|
||||||
const showInviteDialog = async () => {
|
|
||||||
// 这里可以实现邀请功能
|
|
||||||
ElMessage.info('邀请功能开发中...')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 完成任务
|
|
||||||
*/
|
|
||||||
const completeTask = async (taskId) => {
|
|
||||||
try {
|
|
||||||
const response = await api.post(`/tasks/${taskId}/complete`)
|
|
||||||
|
|
||||||
// 更新任务状态
|
|
||||||
const task = tasks.value.find(t => t.id === taskId)
|
|
||||||
if (task) {
|
|
||||||
task.status = 'completed'
|
|
||||||
}
|
|
||||||
|
|
||||||
ElMessage.success('任务完成!')
|
|
||||||
} catch (error) {
|
|
||||||
ElMessage.error('任务完成失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 领取奖励
|
|
||||||
*/
|
|
||||||
const claimReward = async (task) => {
|
|
||||||
task.loading = true
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await api.post(`/tasks/${task.id}/claim`)
|
|
||||||
|
|
||||||
// 更新任务状态和用户积分
|
|
||||||
task.status = 'claimed'
|
|
||||||
userPoints.value += task.points
|
|
||||||
|
|
||||||
ElMessage.success(`获得 ${task.points} 积分!`)
|
|
||||||
} catch (error) {
|
|
||||||
ElMessage.error('领取失败,请重试')
|
|
||||||
} finally {
|
|
||||||
task.loading = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取任务列表
|
|
||||||
*/
|
|
||||||
const getTasks = async () => {
|
|
||||||
loading.value = true
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await api.get('/tasks')
|
|
||||||
tasks.value = response.data.map(task => ({
|
|
||||||
...task,
|
|
||||||
loading: false
|
|
||||||
}))
|
|
||||||
} catch (error) {
|
|
||||||
// 如果API不存在,使用模拟数据
|
|
||||||
tasks.value = [
|
|
||||||
{
|
|
||||||
id: 'first_purchase',
|
|
||||||
category: 'shopping',
|
|
||||||
type: 'purchase',
|
|
||||||
title: '首次购买',
|
|
||||||
description: '在积分商城完成首次购买',
|
|
||||||
points: 50,
|
|
||||||
status: 'pending',
|
|
||||||
loading: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'share_app',
|
|
||||||
category: 'social',
|
|
||||||
type: 'share',
|
|
||||||
title: '分享应用',
|
|
||||||
description: '分享应用给朋友',
|
|
||||||
points: 20,
|
|
||||||
status: 'pending',
|
|
||||||
loading: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'complete_profile',
|
|
||||||
category: 'profile',
|
|
||||||
type: 'profile',
|
|
||||||
title: '完善个人资料',
|
|
||||||
description: '完善头像、姓名等个人信息',
|
|
||||||
points: 30,
|
|
||||||
status: 'pending',
|
|
||||||
progress: 2,
|
|
||||||
target: 5,
|
|
||||||
loading: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'first_transfer',
|
|
||||||
category: 'special',
|
|
||||||
type: 'transfer',
|
|
||||||
title: '首次转账',
|
|
||||||
description: '完成首次转账操作',
|
|
||||||
points: 100,
|
|
||||||
status: 'completed',
|
|
||||||
loading: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取用户积分
|
|
||||||
*/
|
|
||||||
const getUserPoints = async () => {
|
|
||||||
try {
|
|
||||||
const response = await api.get('/user/points')
|
|
||||||
userPoints.value = response.data.points
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取用户积分失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生命周期
|
|
||||||
onMounted(() => {
|
|
||||||
getTasks()
|
|
||||||
getUserPoints()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.task-center {
|
|
||||||
min-height: 100vh;
|
|
||||||
background: #f5f7fa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 0 16px;
|
|
||||||
height: 56px;
|
|
||||||
background: white;
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-left,
|
|
||||||
.nav-right {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-right {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-btn,
|
|
||||||
.points-btn {
|
|
||||||
color: #333;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.points-btn {
|
|
||||||
color: #ff6b35;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-title {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-stats {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-card {
|
|
||||||
background: white;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 20px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-icon {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: white;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-value {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-label {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-categories {
|
|
||||||
padding: 0 16px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-tabs {
|
|
||||||
display: flex;
|
|
||||||
background: white;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 4px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-tab {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: 12px 8px;
|
|
||||||
border-radius: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-tab.active {
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-tab .el-icon {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-list {
|
|
||||||
padding: 0 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-item {
|
|
||||||
background: white;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 16px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-item.completed {
|
|
||||||
border-left: 4px solid #67c23a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-item.claimed {
|
|
||||||
opacity: 0.6;
|
|
||||||
border-left: 4px solid #909399;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-icon {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: white;
|
|
||||||
margin-right: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-content {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-desc {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #666;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-progress {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-progress .el-progress {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-text {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-reward {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reward-points {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #ff6b35;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-state {
|
|
||||||
text-align: center;
|
|
||||||
padding: 60px 20px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-state p {
|
|
||||||
margin-top: 16px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Reference in New Issue
Block a user