first commit

This commit is contained in:
那些花儿
2025-04-24 15:53:31 +08:00
commit f55420fc1d
498 changed files with 205724 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
</template>
<style scoped>
</style>
+372
View File
@@ -0,0 +1,372 @@
<template>
<view class="page-container">
<!-- 顶部搜索区域 -->
<view class="header">
<t-search
v-model="pageForm.searchKeyword"
placeholder="搜索活动"
shape="round"
class="search"
>
<template #action>
<t-button variant="text" @click="filterVisible = true">筛选</t-button>
</template>
</t-search>
</view>
<!-- 筛选弹出层 -->
<t-popup
v-model:visible="filterVisible"
placement="top"
>
<view class="filter">
<view class="filter-header">
<t-button variant="text" @click="handleClearFilter">重置</t-button>
<text class="filter-title">筛选条件</text>
<t-button theme="primary" variant="text" @click="handleSearch">确定</t-button>
</view>
<t-cell-group title="状态">
<t-radio-group v-model="pageForm.status">
<t-radio
v-for="option in statusOptions"
:key="option.value"
:value="option.value"
:label="option.label"
borderless
/>
</t-radio-group>
</t-cell-group>
</view>
</t-popup>
<!-- 活动列表 -->
<scroll-view
style="overflow-y: auto;flex: 1"
:scroll-y="true"
:show-scrollbar="false"
@scrolltolower="onLoadMore"
:refresher-enabled="true"
@refresherrefresh="getListData(true)"
:refresher-triggered="refreshIng"
refresher-background="#f5f5f5"
>
<view class="card"
v-for="item in dataList"
:key="item.id"
@click="navigateToDetail(item.id)"
>
<view class="card-head">
<image :src="item.image" mode="aspectFill" class="card-img"/>
<text class="card-tag" :class="getStatusClass(item.status)">
{{ getStatusText(item.status) }}
</text>
</view>
<view class="card-body">
<view class="card-title">{{ item.title }}</view>
<view class="card-info">
<view class="info-item">
<t-icon name="alarm" size="12px"/>
<text>{{ item.date }}</text>
</view>
<view class="info-item">
<t-icon name="location" size="12px"/>
<text>{{ item.location }}</text>
</view>
<view class="info-item">
<t-icon name="user" size="12px"/>
<text>{{ item.participants }}人已报名</text>
</view>
</view>
<view class="card-footer">
<view class="price">
<text class="price-symbol">¥</text>
<text class="price-value">{{ item.price }}</text>
</view>
<t-button
size="small"
shape="round"
:theme="item.status === 2 ? 'default' : 'primary'"
:disabled="item.status === 2"
>
{{ item.status === 1 ? '立即报名' : item.status === 3 ? '预约提醒' : '已结束' }}
</t-button>
</view>
</view>
</view>
<view class="loading-area">
<t-loading v-if="loading" text="加载中" layout="vertical"/>
<t-divider v-else-if="!hasMore && dataList.length > 0" content="没有更多了"/>
</view>
<t-empty v-if="!loading && !refreshIng && dataList.length === 0"
image="https://tdesign.gtimg.com/mobile/demos/empty1.png" description="暂无活动">
<template #action>
<t-button theme="primary" size="small" shape="round">刷新试试</t-button>
</template>
</t-empty>
</scroll-view>
</view>
</template>
<script setup>
import {ref, reactive, onMounted} from 'vue';
import {Toast} from 'tdesign-mobile-vue';
import {useRequest} from "@/util/request";
// 筛选选项
const statusOptions = [
{value: '', label: '全部'},
{value: '1', label: '进行中'},
{value: '2', label: '已结束'},
{value: '3', label: '未开始'}
];
const pageForm = reactive({
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: null,
status: null
})
// 数据与状态
const dataList = ref([]);
const loading = ref(false);
const hasMore = ref(true);
const refreshIng = ref(false);
const filterVisible = ref(false);
// 搜索表单
const searchForm = reactive({
keyword: '',
status: ''
});
// 获取状态样式类
const getStatusClass = (status) => {
return {
1: 'status-active',
2: 'status-ended',
3: 'status-upcoming'
}[status] || '';
};
// 获取状态文本
const getStatusText = (status) => {
return {
1: '报名中',
2: '已结束',
3: '即将开始'
}[status] || '未知状态';
};
// 获取列表数据
const getListData = async (isRefresh = false) => {
if (isRefresh) {
refreshIng.value = true;
pageForm.pageNumber = 1;
} else {
loading.value = true
}
await new Promise(resolve => setTimeout(resolve, 1000));
try {
const {code, data, msg} = await useRequest().post('/client/activity/pageData', {
...pageForm
})
if (code === 0) {
if (isRefresh) {
dataList.value = data.list;
} else {
dataList.value = [...dataList.value, ...data.list];
}
hasMore.value = dataList.value.length < data.totalCount;
pageForm.pageNumber++;
console.log(hasMore.value)
} else {
console.error('获取列表失败', msg)
Toast({message: '获取列表失败', theme: 'error'});
}
} catch (error) {
console.error('获取列表失败', error);
Toast({message: '获取列表失败', theme: 'error'});
} finally {
loading.value = false;
refreshIng.value = false;
}
};
// 搜索处理
const handleSearch = () => {
hasMore.value = true;
dataList.value = [];
getListData();
};
// 清空筛选
const handleClearFilter = () => {
pageForm.keyword = null
pageForm.status = null
filterVisible.value = false;
};
// 加载更多
const onLoadMore = () => {
if (loading.value || !hasMore.value) return;
getListData();
};
// 跳转详情
const navigateToDetail = (id) => {
uni.navigateTo({
url: `/pages/activity/detail/index?id=${id}`
});
};
// 初始化
onMounted(() => {
getListData();
});
</script>
<style scoped>
.header {
background-color: #fff;
padding: 10px 16px;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
position: sticky;
top: 0;
z-index: 10;
}
.search {
--td-search-bg-color: #f0f0f0;
}
.filter {
background-color: #fff;
border-radius: 0 0 16px 16px;
padding: 0 16px 20px;
}
.filter-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 0;
border-bottom: 1px solid #eee;
}
.filter-title {
font-weight: bold;
font-size: 16px;
}
.card {
background-color: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
margin: 10px;
}
.card-head {
position: relative;
height: 160px;
}
.card-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.card-tag {
position: absolute;
top: 12px;
right: 0;
padding: 4px 12px;
color: #fff;
font-size: 12px;
font-weight: bold;
border-radius: 4px 0 0 4px;
}
.status-active {
background-color: #28c445;
}
.status-ended {
background-color: #999;
}
.status-upcoming {
background-color: #ff9800;
}
.card-body {
padding: 16px;
}
.card-title {
font-size: 16px;
font-weight: bold;
line-height: 1.4;
margin-bottom: 12px;
color: #333;
}
.card-info {
margin-bottom: 12px;
}
.info-item {
display: flex;
align-items: center;
font-size: 13px;
color: #666;
margin-bottom: 6px;
}
.info-item :deep(i) {
margin-right: 6px;
color: #999;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #f0f0f0;
padding-top: 10px;
}
.price {
display: flex;
align-items: baseline;
}
.price-symbol {
font-size: 14px;
color: #ff5050;
font-weight: bold;
}
.price-value {
font-size: 22px;
color: #ff5050;
font-weight: bold;
}
.loading-area {
padding: 16px 0;
text-align: center;
}
</style>
@@ -0,0 +1,276 @@
<template>
<view class="page-container">
<view class="act-info">
<view class="act-title">奋进新征程 运动促健康 2024晴江第六届"牧城之夜"荧光跑</view>
<view class="act-meta">
<view class="act-meta-item">22222</view>
<view class="act-meta-item">22222222222222222222</view>
</view>
</view>
<view class="form-area">
<t-form
ref="formRef"
:data="formData"
reset-type="initial"
show-error-message
label-align="left"
scroll-to-first-error="auto"
>
<view class="form-block">
<view class="form-block-title">
<t-icon name="institution"></t-icon>
单位信息
</view>
<t-form-item label="参加单位" name="unitName" :rules="[{required:true,message: '请输入单位名称'}]">
<t-input v-model="formData.unitName" borderless placeholder="请输入参加单位名称"></t-input>
</t-form-item>
<t-form-item label="联系人" name="contactName" :rules="[{required:true,message: '请输入联系人姓名'}]">
<t-input v-model="formData.contactName" borderless placeholder="请输入联系人姓名"></t-input>
</t-form-item>
<t-form-item label="联系方式" name="contactPhone" :rules="[{required:true,message: '请输入联系电话'}]">
<t-input v-model="formData.contactPhone" borderless placeholder="请输入联系电话"></t-input>
</t-form-item>
</view>
<view class="form-block">
<view class="form-block-title">
<t-icon name="usergroup"></t-icon>
报名人员信息
</view>
<view v-for="(user,index) in formData.userList" :key="index" class="user-card">
<view class="user-card-header">
<view class="user-card-header-title">
<span>{{ index + 1 }}</span>
</view>
<view class="remove" @click="formData.userList.splice(index, 1)">
<t-icon name="delete" size="18px"></t-icon>
</view>
</view>
<t-form-item label="姓名" :name="`userList[${index}].name`"
:rules="[{required:true,message: '请输入姓名'}]">
<t-input v-model="user.name" borderless placeholder="请输入内容"></t-input>
</t-form-item>
<t-form-item label="性别" :name="`userList[${index}].sex`" :rules="[{required:true,message: '请选择性别'}]">
<t-radio-group v-model="user.sex" borderless class="radio-box">
<t-radio :block="false" label="男" value="男"/>
<t-radio :block="false" label="女" value="女"/>
</t-radio-group>
</t-form-item>
<t-form-item label="职务" :name="`userList[${index}].job`" :rules="[{required:true,message: '请输入职务'}]">
<t-input v-model="user.job" borderless placeholder="请输入职务"></t-input>
</t-form-item>
<t-form-item label="身份证号" :name="`userList[${index}].idCard`"
:rules="[{required:true,message: '请输入身份证号码'},{idcard:true, message: '请输入正确的身份证号码'}]">
<t-input v-model="user.idCard" borderless placeholder="请输入身份证号码"></t-input>
</t-form-item>
<t-form-item label="联系电话" :name="`userList[${index}].phone`"
:rules="[{required:true,message: '请输入联系电话'},{telnumber:true, message: '请输入正确的联系电话'}]">
<t-input v-model="user.phone" borderless placeholder="请输入联系电话"></t-input>
</t-form-item>
<t-form-item label="是否住宿" :name="`userList[${index}].sleep`"
:rules="[{required:true,message: '请选择是否住宿'}]">
<t-radio-group v-model="user.sleep" class="radio-box">
<t-radio :block="false" name="radio" value="1" label="是"/>
<t-radio :block="false" name="radio" value="2" label="否"/>
</t-radio-group>
</t-form-item>
</view>
</view>
</t-form>
<view class="add-user" @click="formData.userList.push({})">
<t-icon name="plus" size="24px"></t-icon>
<text>添加人员</text>
</view>
</view>
<view class="footer">
<view class="agreement-checkbox">
<t-checkbox label="多选" icon="rectangle" v-model:checked="agreementChecked" default-checked>
<label>我已阅读并同意
<text class="agreement-link">《参赛承诺书》</text>
</label>
</t-checkbox>
</view>
<t-button
block
theme="primary"
size="large"
shape="round"
@click="onSubmit"
>
提交报名
</t-button>
</view>
</view>
</template>
<script setup>
import {ref} from 'vue'
const agreementChecked = ref(false)
const formRef = ref(null)
const formData = ref({
unitName: null,
userList: []
})
function onSubmit() {
console.log(formRef)
console.log(formRef.value)
formRef.value.validate()
}
</script>
<style scoped lang="less">
.act-info {
position: fixed;
top: 44px;
left: 0;
right: 0;
background: white;
padding: 12px 16px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
z-index: 9;
max-width: 750px;
margin: 0 auto;
width: 100%;
height: auto;
min-height: 70px;
display: flex;
flex-direction: column;
justify-content: center;
.act-title {
font-size: 16px;
font-weight: 500;
margin-bottom: 8px;
line-height: 1.4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.event-meta {
display: flex;
font-size: 13px;
color: #666;
margin-top: 2px;
.event-meta-item {
display: flex;
align-items: center;
margin-right: 16px;
white-space: nowrap;
}
}
}
.form-area{
flex: 1;
overflow-y: auto;
margin-top: 100px;
margin-bottom: 130px;
}
.form-block {
padding: 20px 16px;
background: white;
margin-bottom: 10px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
.form-block-title {
font-size: 16px;
font-weight: 500;
margin-bottom: 16px;
color: #333;
display: flex;
align-items: center;
.t-icon {
margin-right: 5px;
color: var(--td-brand-color);
}
}
}
.user-card {
background: white;
margin-bottom: 20px;
position: relative;
border-left: 3px solid #e74c3c;
padding-left: 12px;
.user-card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
.user-card-header-title {
font-weight: 500;
color: #333;
font-size: 15px;
display: flex;
align-items: center;
span {
display: flex;
justify-content: center;
align-items: center;
width: 24px;
height: 24px;
background-color: #e74c3c;
color: white;
border-radius: 50%;
font-size: 14px;
margin-right: 8px;
}
}
.remove {
color: #e74c3c;
//font-size: 14px;
display: flex;
align-items: center;
background: none;
border: none;
cursor: pointer;
}
}
}
.add-user {
padding: 15px;
text-align: center;
color: #e74c3c;
font-weight: 500;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
background: #ffffff;
}
.radio-box {
width: 100%;
display: flex;
column-gap: 20px;
}
.footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 0 16px 16px;
background-color: white;
box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1);
z-index: 10;
max-width: 750px;
margin: 0 auto;
width: 100%;
}
</style>
+313
View File
@@ -0,0 +1,313 @@
<template>
<view class="page-container">
<t-dropdown-menu @menu-opened="handleMenuOpened" @menu-closed="handleMenuClosed">
<t-dropdown-item :options="actOptions" :value="pageForm.actId" @change="actChange" />
</t-dropdown-menu>
<div class="content-area">
<!-- 团队信息卡片 -->
<div class="team-card">
<div class="team-banner">
<div class="team-logo">
<i class="bi bi-people-fill" v-if="!team.logoUrl"></i>
<img :src="team.logoUrl" alt="团队logo" v-if="team.logoUrl">
</div>
<div class="team-info">
<div class="team-name">{{ team.name }}</div>
<div class="team-meta">创建于 {{ team.createdDate }}</div>
<div class="team-id">团队ID: {{ team.id }}</div>
</div>
<div class="event-name">{{ team.eventName }}</div>
</div>
<div class="team-detail">
<div class="team-stat-row">
<div class="team-stat-item">
<div class="team-stat-value">{{ team.memberCount }}</div>
<div class="team-stat-label">团队成员</div>
</div>
<div class="team-stat-item">
<div class="team-stat-value">{{ team.rank }}</div>
<div class="team-stat-label">当前排名</div>
</div>
<div class="team-stat-item">
<div class="team-stat-value">{{ team.score }}</div>
<div class="team-stat-label">团队积分</div>
</div>
</div>
<div style="font-size: 14px; color: #666; line-height: 1.6;">
{{ team.description }}
</div>
</div>
</div>
<!-- 团队成员 -->
<div class="team-section">
<div class="section-header">
<div class="section-title">
<i class="bi bi-people"></i>团队成员
</div>
</div>
<div class="member-list">
<div class="member-item" v-for="member in team.members" :key="member.id">
<div class="member-avatar">
<img :src="member.avatar" :alt="member.name" onerror="this.src='data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iI2YwZjBmMCIvPjx0ZXh0IHg9IjUwJSIgeT0iNTAlIiBmb250LXNpemU9IjIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBhbGlnbm1lbnQtYmFzZWxpbmU9Im1pZGRsZSIgZm9udC1mYW1pbHk9IkFyaWFsLCBzYW5zLXNlcmlmIiBmaWxsPSIjNTU1Ij57eyBtZW1iZXIubmFtZS5jaGFyQXQoMCkgfX08L3RleHQ+PC9zdmc+'">
</div>
<div class="member-info">
<div class="member-name">
{{ member.name }}
<span class="member-role" v-if="member.role === 'leader'">队长</span>
<span class="member-role" v-else-if="member.role === 'admin'" style="background-color: #ff9a5a;">管理员</span>
</div>
<div class="member-detail">
<div class="member-detail-item">
<i class="bi bi-gender-ambiguous"></i>
<span>{{ member.gender }}</span>
</div>
<div class="member-detail-item">
<i class="bi bi-building"></i>
<span>{{ member.organization }}</span>
</div>
</div>
</div>
<div class="member-actions">
<i class="bi bi-three-dots-vertical"></i>
</div>
</div>
</div>
<!-- 当前角色与申请队长 -->
<div v-if="currentUserRole !== 'leader'">
<div class="role-notice" v-if="currentUserRole === 'admin'">
<i class="bi bi-info-circle"></i>
您当前是管理员身份,拥有团队管理权限
</div>
<div class="role-notice" v-else>
<i class="bi bi-info-circle"></i>
您当前是普通成员身份
</div>
<button class="apply-leader-btn" @click="showLeaderConfirm">
<i class="bi bi-award"></i>申请成为队长
</button>
</div>
<div class="role-notice" v-else>
<i class="bi bi-check-circle"></i>
您当前是队长身份,拥有团队所有权限
</div>
</div>
<!-- 项目报名按钮 -->
<div class="team-section">
<button class="register-btn" @click="goToEventRegistration">
<i class="bi bi-calendar-check"></i>
项目报名
</button>
</div>
</div>
</view>
</template>
<script setup>
import {ref,reactive} from "vue";
const actOptions = ref([])
const pageForm = reactive({
actId: null,
})
const teamId = ''
const team = reactive({
id: teamId,
name: '江苏健康跑团',
logoUrl: null,
createdDate: '2023-10-15',
eventId: '',
eventName: '',
memberCount: 12,
rank: 5,
score: 256,
description: '我们是一支来自江苏省的健康跑团队,致力于推广健康跑步文化,鼓励大家积极参与体育活动,共同展现江苏的活力风采。',
// 团队成员
members: [
{
id: '101',
name: '张伟',
role: 'leader',
gender: '男',
organization: '江苏体育学院',
avatar: null
},
{
id: '102',
name: '李娜',
role: 'admin',
gender: '女',
organization: '南京体育局',
avatar: null
},
{
id: '103',
name: '王强',
role: 'member',
gender: '男',
organization: '南京体育学院',
avatar: null
},
{
id: '104',
name: '刘芳',
role: 'member',
gender: '女',
organization: '江苏大学',
avatar: null
},
{
id: '105',
name: '陈明',
role: 'member',
gender: '男',
organization: '苏州体育中心',
avatar: null
}
]
});
function handleMenuOpened(){
}
function handleMenuClosed(){}
function actChange(val){
console.log(val)
}
</script>
<style scoped lang="less">
/* 主体内容区 */
.content-area {
}
/* 团队信息卡片 */
.team-card {
background-color: white;
margin: 15px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
overflow: hidden;
}
.team-banner {
position: relative;
height: 120px;
background: linear-gradient(135deg, #e74c3c, #ff7675);
display: flex;
align-items: center;
padding: 20px;
}
.team-logo {
width: 80px;
height: 80px;
border-radius: 50%;
background-color: white;
display: flex;
justify-content: center;
align-items: center;
margin-right: 15px;
border: 2px solid rgba(255, 255, 255, 0.8);
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.team-logo img {
width: 100%;
height: 100%;
object-fit: cover;
}
.team-logo i {
font-size: 40px;
color: #e74c3c;
}
.team-info {
flex: 1;
color: white;
}
.team-name {
font-size: 20px;
font-weight: 600;
margin-bottom: 6px;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.team-meta {
font-size: 13px;
opacity: 0.95;
}
.team-id {
display: inline-block;
background-color: rgba(255, 255, 255, 0.2);
padding: 2px 8px;
border-radius: 10px;
margin-top: 6px;
font-size: 12px;
}
.event-name {
position: absolute;
bottom: 10px;
right: 15px;
background-color: rgba(0, 0, 0, 0.2);
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
color: white;
}
/* 团队详情内容 */
.team-detail {
padding: 15px;
}
.team-stat-row {
display: flex;
margin-bottom: 15px;
border-bottom: 1px solid #f0f0f0;
padding-bottom: 15px;
}
.team-stat-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
padding: 5px 0;
}
.team-stat-value {
font-size: 22px;
font-weight: 600;
color: #e74c3c;
margin-bottom: 5px;
}
.team-stat-label {
font-size: 13px;
color: #666;
}
</style>
+267
View File
@@ -0,0 +1,267 @@
<template>
<view class="page-container">
<!-- 顶部背景和内容区 -->
<view class="header">
<image class="header-bg" src="https://erp-bucket.pek3b.qingstor.com/assistant/89c4b573-c54f-467a-b703-0bc44679ab08.png" mode="aspectFill"></image>
</view>
<!-- 功能菜单区 -->
<view class="menu-container">
<view class="menu-item" @click="navigateTo('/pages/activity/list/index')">
<view class="menu-icon-wrapper red-bg">
<view class="menu-icon trophy-icon"></view>
</view>
<view class="menu-text">赛事报名</view>
</view>
<view class="menu-item" @click="navigateTo('/pages/scan/index')">
<view class="menu-icon-wrapper orange-bg">
<view class="menu-icon qrcode-icon"></view>
</view>
<view class="menu-text">扫码签到</view>
</view>
<view class="menu-item" @click="navigateTo('/pages/activity/team/index')">
<view class="menu-icon-wrapper yellow-bg">
<view class="menu-icon team-icon"></view>
<view class="badge">3</view>
</view>
<view class="menu-text">我的团队</view>
</view>
<view class="menu-item" @click="navigateTo('/pages/activity/team/index')">
<view class="menu-icon-wrapper blue-bg">
<view class="menu-icon star-icon"></view>
</view>
<view class="menu-text">项目报名</view>
</view>
</view>
<!-- 精选内容区 -->
<view class="content-section">
<view class="section-header">
<view class="section-title">精选活动</view>
<view class="section-more" @click="navigateTo('/pages/activity/index')">更多</view>
</view>
<view class="activity-list">
<view class="activity-item" @click="navigateTo('/pages/process/index')">
<image class="activity-image" src="https://erp-bucket.pek3b.qingstor.com/assistant/746c37d6-018d-4c64-8a98-ea9ec8b0b3b5.png" mode="widthFix"></image>
<view class="activity-info">
<view class="activity-title">一分钟了解运动会流程</view>
<view class="activity-meta">
<text class="activity-time">6月15日-20日</text>
<text class="activity-location">江苏省体育中心</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { onMounted } from "vue";
function navigateTo(url) {
uni.navigateTo({
url
})
}
onMounted(()=>{
console.log('...........')
uni.showToast({
title: '欢迎使用',
icon: 'none',
duration: 2000
})
})
</script>
<style lang="less" scoped>
// 头部区域样式
.header {
position: relative;
height: 245px;
overflow: hidden;
}
.header-bg {
width: 100%;
height: 100%;
object-fit: cover;
}
// 菜单区域样式
.menu-container {
display: flex;
justify-content: space-around;
padding: 20px;
background-color: #fff;
border-radius: 15px;
margin: -30px 15px 15px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
z-index: 10;
}
.menu-item {
display: flex;
flex-direction: column;
align-items: center;
width: 22%;
}
.menu-icon-wrapper {
width: 50px;
height: 50px;
border-radius: 12px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.red-bg {
background: linear-gradient(135deg, #ff7676, #f45a5a);
}
.orange-bg {
background: linear-gradient(135deg, #ffa76a, #f89f58);
}
.yellow-bg {
background: linear-gradient(135deg, #ffd166, #f8c158);
}
.blue-bg {
background: linear-gradient(135deg, #72a1ff, #5c7cfa);
}
.menu-icon {
width: 28px;
height: 28px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.trophy-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M19 5h-2V3H7v2H5c-1.1 0-2 .9-2 2v1c0 2.55 1.92 4.63 4.39 4.94.63 1.5 1.98 2.63 3.61 2.96V19H7v2h10v-2h-4v-3.1c1.63-.33 2.98-1.46 3.61-2.96C19.08 12.63 21 10.55 21 8V7c0-1.1-.9-2-2-2zM5 8V7h2v3.82C5.84 10.4 5 9.3 5 8zm14 0c0 1.3-.84 2.4-2 2.82V7h2v1z'/%3E%3C/svg%3E");
}
.qrcode-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zM13 3v8h8V3h-8zm6 6h-4V5h4v4zM13 13h2v2h-2zM15 15h2v2h-2zM13 17h2v2h-2zM17 17h2v2h-2zM19 19h2v2h-2zM15 19h2v2h-2zM17 13h2v2h-2zM19 15h2v2h-2z'/%3E%3C/svg%3E");
}
.team-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5s-3 1.34-3 3 1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z'/%3E%3C/svg%3E");
}
.star-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'/%3E%3C/svg%3E");
}
.badge {
position: absolute;
top: -5px;
right: -5px;
background-color: #ff4d4f;
color: white;
border-radius: 10px;
min-width: 18px;
height: 18px;
font-size: 12px;
line-height: 18px;
text-align: center;
padding: 0 5px;
font-weight: bold;
box-shadow: 0 2px 4px rgba(255, 77, 79, 0.3);
}
.menu-text {
margin-top: 10px;
font-size: 14px;
color: #333;
font-weight: 500;
}
// 内容区域样式
.content-section {
margin: 0 0 15px;
padding: 15px;
background-color: #fff;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
position: relative;
padding-left: 10px;
}
.section-title::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 16px;
background: linear-gradient(to bottom, #ff6b6b, #e83a3a);
border-radius: 3px;
}
.section-more {
font-size: 14px;
color: #666;
}
// 活动列表样式
.activity-list {
width: 100%;
}
.activity-item {
width: 100%;
margin-bottom: 15px;
}
.activity-item:last-child {
margin-bottom: 0;
}
.activity-image {
width: 100%;
}
.activity-info {
padding: 10px 0;
}
.activity-title {
font-size: 16px;
font-weight: 500;
color: #333;
margin-bottom: 5px;
}
.activity-meta {
display: flex;
font-size: 12px;
color: #999;
}
.activity-time {
margin-right: 15px;
}
</style>
+11
View File
@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
我的页面
</template>
<style scoped>
</style>