From d98457e1ddedf65dad38a4e03294ac1a1a314995 Mon Sep 17 00:00:00 2001
From: liu <2302563948@qq.com>
Date: Wed, 1 Jul 2026 22:16:15 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E3=80=81=E6=B6=88=E6=81=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../TaskCard/ActivityCard/index.less | 27 ++
.../TaskCard/ActivityCard/index.tsx | 42 ++++
.../TaskCard/CarpoolCard/index.less | 20 ++
src/components/TaskCard/CarpoolCard/index.tsx | 37 +++
.../TaskCard/ExpressCard/index.less | 10 +
src/components/TaskCard/ExpressCard/index.tsx | 41 ++++
src/components/TaskCard/HelpCard/index.less | 10 +
src/components/TaskCard/HelpCard/index.tsx | 36 +++
.../TaskCard/SecondhandCard/index.less | 15 ++
.../TaskCard/SecondhandCard/index.tsx | 57 +++++
src/components/TaskCard/index.less | 100 ++++++++
src/components/TaskCard/index.tsx | 30 +++
src/mock/messages.ts | 103 ++++++++
src/mock/tasks.ts | 133 ++++++++++
src/pages/messages/index.less | 168 +++++++++++--
src/pages/messages/index.tsx | 99 +++++++-
src/pages/profile/index.less | 230 ++++++++++++++++--
src/pages/profile/index.tsx | 159 +++++++++++-
src/pages/tasks/index.less | 94 ++++++-
src/pages/tasks/index.tsx | 103 +++++++-
src/types/message.ts | 25 ++
src/types/task.ts | 28 +++
22 files changed, 1504 insertions(+), 63 deletions(-)
create mode 100644 src/components/TaskCard/ActivityCard/index.less
create mode 100644 src/components/TaskCard/ActivityCard/index.tsx
create mode 100644 src/components/TaskCard/CarpoolCard/index.less
create mode 100644 src/components/TaskCard/CarpoolCard/index.tsx
create mode 100644 src/components/TaskCard/ExpressCard/index.less
create mode 100644 src/components/TaskCard/ExpressCard/index.tsx
create mode 100644 src/components/TaskCard/HelpCard/index.less
create mode 100644 src/components/TaskCard/HelpCard/index.tsx
create mode 100644 src/components/TaskCard/SecondhandCard/index.less
create mode 100644 src/components/TaskCard/SecondhandCard/index.tsx
create mode 100644 src/components/TaskCard/index.less
create mode 100644 src/components/TaskCard/index.tsx
create mode 100644 src/mock/messages.ts
create mode 100644 src/mock/tasks.ts
create mode 100644 src/types/message.ts
create mode 100644 src/types/task.ts
diff --git a/src/components/TaskCard/ActivityCard/index.less b/src/components/TaskCard/ActivityCard/index.less
new file mode 100644
index 0000000..81c03d5
--- /dev/null
+++ b/src/components/TaskCard/ActivityCard/index.less
@@ -0,0 +1,27 @@
+.activity-card {
+ .type-badge.activity {
+ background: #e8fff0;
+ color: #07c160;
+ font-size: 22px;
+ padding: 4px 12px;
+ border-radius: 6px;
+ font-weight: 500;
+ }
+ .participants-count {
+ font-size: 24px;
+ color: #646566;
+ }
+ .progress-bar-wrap {
+ margin: 16px 0 8px;
+ height: 8px;
+ background: #f2f3f5;
+ border-radius: 4px;
+ overflow: hidden;
+ .progress-bar {
+ height: 100%;
+ background: linear-gradient(90deg, #07c160, #1989fa);
+ border-radius: 4px;
+ transition: width 0.3s;
+ }
+ }
+}
diff --git a/src/components/TaskCard/ActivityCard/index.tsx b/src/components/TaskCard/ActivityCard/index.tsx
new file mode 100644
index 0000000..f2e1ab5
--- /dev/null
+++ b/src/components/TaskCard/ActivityCard/index.tsx
@@ -0,0 +1,42 @@
+import type { Task } from '@/types/task'
+import { View, Text, Image } from '@tarojs/components'
+import './index.less'
+
+interface Props { task: Task }
+
+export default function ActivityCard({ task }: Props) {
+ const progress = task.maxParticipants
+ ? Math.round(((task.participants || 0) / task.maxParticipants) * 100)
+ : 0
+
+ return (
+
+
+
+
+ 校园活动
+ 👥 {task.participants}/{task.maxParticipants}人
+
+ {task.title}
+ {task.desc}
+
+
+ {/* 参与进度条 */}
+ {task.maxParticipants && (
+
+
+
+ )}
+
+
+
+ {task.publisher.name}
+
+
+ 📍 {task.location}
+ 🕐 {task.time}
+
+
+
+ )
+}
diff --git a/src/components/TaskCard/CarpoolCard/index.less b/src/components/TaskCard/CarpoolCard/index.less
new file mode 100644
index 0000000..8b5034c
--- /dev/null
+++ b/src/components/TaskCard/CarpoolCard/index.less
@@ -0,0 +1,20 @@
+.carpool-card {
+ .type-badge.carpool {
+ background: #f0e8ff;
+ color: #7b4ac7;
+ font-size: 22px;
+ padding: 4px 12px;
+ border-radius: 6px;
+ font-weight: 500;
+ }
+ .carpool-right {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ .seat-info {
+ font-size: 22px;
+ color: #07c160;
+ margin-top: 4px;
+ }
+ }
+}
diff --git a/src/components/TaskCard/CarpoolCard/index.tsx b/src/components/TaskCard/CarpoolCard/index.tsx
new file mode 100644
index 0000000..1c73786
--- /dev/null
+++ b/src/components/TaskCard/CarpoolCard/index.tsx
@@ -0,0 +1,37 @@
+import type { Task } from '@/types/task'
+import { View, Text, Image } from '@tarojs/components'
+import './index.less'
+
+interface Props { task: Task }
+
+export default function CarpoolCard({ task }: Props) {
+ return (
+
+
+
+
+ 拼车出行
+
+ {task.title}
+ {task.desc}
+
+
+ {task.reward}
+ {task.participants != null && task.maxParticipants != null && (
+ 余{task.maxParticipants - task.participants}座
+ )}
+
+
+
+
+
+ {task.publisher.name}
+
+
+ 📍 {task.location}
+ ⏰ {task.deadline || task.time}
+
+
+
+ )
+}
diff --git a/src/components/TaskCard/ExpressCard/index.less b/src/components/TaskCard/ExpressCard/index.less
new file mode 100644
index 0000000..e99e97b
--- /dev/null
+++ b/src/components/TaskCard/ExpressCard/index.less
@@ -0,0 +1,10 @@
+.express-card {
+ .type-badge.express {
+ background: #e8f4ff;
+ color: #1989fa;
+ font-size: 22px;
+ padding: 4px 12px;
+ border-radius: 6px;
+ font-weight: 500;
+ }
+}
diff --git a/src/components/TaskCard/ExpressCard/index.tsx b/src/components/TaskCard/ExpressCard/index.tsx
new file mode 100644
index 0000000..2bfdcfb
--- /dev/null
+++ b/src/components/TaskCard/ExpressCard/index.tsx
@@ -0,0 +1,41 @@
+import type { Task } from '@/types/task'
+import { View, Text, Image } from '@tarojs/components'
+import { Tag } from '@antmjs/vantui'
+import './index.less'
+
+interface Props { task: Task }
+
+const STATUS_MAP: Record = {
+ open: '待接单',
+ progress: '进行中',
+ done: '已完成',
+ cancelled: '已取消',
+}
+
+export default function ExpressCard({ task }: Props) {
+ return (
+
+
+
+
+ 快递代取
+ {STATUS_MAP[task.status]}
+
+ {task.title}
+ {task.desc}
+
+ {task.reward}
+
+
+
+
+ {task.publisher.name}
+
+
+ 📍 {task.location}
+ ⏰ {task.deadline || task.time}
+
+
+
+ )
+}
diff --git a/src/components/TaskCard/HelpCard/index.less b/src/components/TaskCard/HelpCard/index.less
new file mode 100644
index 0000000..def0794
--- /dev/null
+++ b/src/components/TaskCard/HelpCard/index.less
@@ -0,0 +1,10 @@
+.help-card {
+ .type-badge.help {
+ background: #fff0f0;
+ color: #ee0a24;
+ font-size: 22px;
+ padding: 4px 12px;
+ border-radius: 6px;
+ font-weight: 500;
+ }
+}
diff --git a/src/components/TaskCard/HelpCard/index.tsx b/src/components/TaskCard/HelpCard/index.tsx
new file mode 100644
index 0000000..30a5c4e
--- /dev/null
+++ b/src/components/TaskCard/HelpCard/index.tsx
@@ -0,0 +1,36 @@
+import type { Task } from '@/types/task'
+import { View, Text, Image } from '@tarojs/components'
+import { Tag } from '@antmjs/vantui'
+import './index.less'
+
+interface Props { task: Task }
+
+export default function HelpCard({ task }: Props) {
+ return (
+
+
+
+
+ 求助
+ {task.tags?.map((t) => (
+ {t}
+ ))}
+
+ {task.title}
+ {task.desc}
+
+ {task.reward}
+
+
+
+
+ {task.publisher.name}
+
+
+ 📍 {task.location}
+ 🕐 {task.time}
+
+
+
+ )
+}
diff --git a/src/components/TaskCard/SecondhandCard/index.less b/src/components/TaskCard/SecondhandCard/index.less
new file mode 100644
index 0000000..a46d646
--- /dev/null
+++ b/src/components/TaskCard/SecondhandCard/index.less
@@ -0,0 +1,15 @@
+.secondhand-card {
+ .type-badge.secondhand {
+ background: #fff3e8;
+ color: #ff976a;
+ font-size: 22px;
+ padding: 4px 12px;
+ border-radius: 6px;
+ font-weight: 500;
+ }
+ .tag-row {
+ display: flex;
+ gap: 8px;
+ margin-top: 10px;
+ }
+}
diff --git a/src/components/TaskCard/SecondhandCard/index.tsx b/src/components/TaskCard/SecondhandCard/index.tsx
new file mode 100644
index 0000000..6674738
--- /dev/null
+++ b/src/components/TaskCard/SecondhandCard/index.tsx
@@ -0,0 +1,57 @@
+import type { Task } from '@/types/task'
+import { View, Text } from '@tarojs/components'
+import { Image as VantImage, Tag } from '@antmjs/vantui'
+import './index.less'
+
+interface Props { task: Task }
+
+export default function SecondhandCard({ task }: Props) {
+ return (
+
+
+ {task.images && task.images.length > 0 && (
+
+ )}
+
+
+ 二手交易
+
+ {task.title}
+ {task.desc}
+ {task.tags && (
+
+ {task.tags.map((t) => (
+ {t}
+ ))}
+
+ )}
+
+ {task.reward}
+
+
+
+
+ {task.publisher.name}
+
+
+ 📍 {task.location}
+ 🕐 {task.time}
+
+
+
+ )
+}
diff --git a/src/components/TaskCard/index.less b/src/components/TaskCard/index.less
new file mode 100644
index 0000000..e7fc5db
--- /dev/null
+++ b/src/components/TaskCard/index.less
@@ -0,0 +1,100 @@
+/* ========================================
+ 任务卡片通用样式(各类型卡片共享)
+ ======================================== */
+
+.task-card {
+ background: #fff;
+ border-radius: 16px;
+ padding: 24px;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
+
+ .card-top {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+
+ .task-info {
+ flex: 1;
+ overflow: hidden;
+ margin-right: 16px;
+ }
+
+ .task-type-row {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 12px;
+ }
+
+ .task-title {
+ display: block;
+ font-size: 32px;
+ font-weight: 500;
+ color: #1a1a1a;
+ line-height: 1.4;
+ margin-bottom: 8px;
+ }
+
+ .task-desc {
+ display: block;
+ font-size: 26px;
+ color: #969799;
+ line-height: 1.5;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+ }
+
+ .task-reward,
+ .task-price {
+ font-size: 36px;
+ font-weight: 600;
+ color: #ee0a24;
+ white-space: nowrap;
+ flex-shrink: 0;
+ }
+
+ .task-status {
+ font-size: 24px;
+ color: #07c160;
+ }
+ }
+
+ .card-bottom {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 20px;
+ padding-top: 16px;
+ border-top: 1px solid #f2f3f5;
+
+ .publisher {
+ display: flex;
+ align-items: center;
+
+ .pub-avatar {
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ margin-right: 10px;
+ }
+
+ .pub-name {
+ font-size: 26px;
+ color: #323233;
+ }
+ }
+
+ .task-meta {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+
+ .meta-item {
+ font-size: 24px;
+ color: #969799;
+ }
+ }
+ }
+}
diff --git a/src/components/TaskCard/index.tsx b/src/components/TaskCard/index.tsx
new file mode 100644
index 0000000..8897342
--- /dev/null
+++ b/src/components/TaskCard/index.tsx
@@ -0,0 +1,30 @@
+import type { Task } from '@/types/task'
+import ExpressCard from './ExpressCard'
+import SecondhandCard from './SecondhandCard'
+import HelpCard from './HelpCard'
+import ActivityCard from './ActivityCard'
+import CarpoolCard from './CarpoolCard'
+import './index.less'
+
+interface TaskCardProps {
+ task: Task
+}
+
+/** 根据 task.type 自动选择对应的卡片组件 */
+export default function TaskCard({ task }: TaskCardProps) {
+ switch (task.type) {
+ case 'secondhand':
+ return
+ case 'help':
+ return
+ case 'activity':
+ return
+ case 'carpool':
+ return
+ case 'express':
+ default:
+ return
+ }
+}
+
+export { ExpressCard, SecondhandCard, HelpCard, ActivityCard, CarpoolCard }
diff --git a/src/mock/messages.ts b/src/mock/messages.ts
new file mode 100644
index 0000000..c8c9c84
--- /dev/null
+++ b/src/mock/messages.ts
@@ -0,0 +1,103 @@
+import type { ChatItem } from '@/types/message'
+
+/** 消息列表:置顶系统消息 + 聊天消息 */
+export const chatList: ChatItem[] = [
+ // === 置顶系统消息 ===
+ {
+ id: 'sys1',
+ type: 'system',
+ title: '📢 系统通知',
+ content: '新学期选课系统将于8月25日开放,请同学们提前做好准备...',
+ time: '昨天',
+ pinned: true,
+ },
+ {
+ id: 'sys2',
+ type: 'system',
+ title: '🔔 校园公告',
+ content: '图书馆暑期开放时间调整通知:7月15日-8月20日期间开放时间调整为...',
+ time: '2天前',
+ pinned: true,
+ },
+
+ // === 用户对话(私信/同学) ===
+ {
+ id: 'chat1',
+ type: 'chat',
+ avatar: 'https://picsum.photos/seed/avat1/100/100',
+ name: '张同学',
+ role: 'user',
+ lastMessage: '好的,那明天下午3点图书馆见,我带教材过去',
+ time: '10:32',
+ unread: 3,
+ online: true,
+ },
+ {
+ id: 'chat2',
+ type: 'chat',
+ avatar: 'https://picsum.photos/seed/avat2/100/100',
+ name: '李同学',
+ role: 'user',
+ lastMessage: '那个快递我已经帮你取了,放你宿舍一楼前台了',
+ time: '09:15',
+ unread: 1,
+ online: true,
+ },
+ {
+ id: 'chat3',
+ type: 'chat',
+ avatar: 'https://picsum.photos/seed/avat3/100/100',
+ name: '王同学',
+ role: 'user',
+ lastMessage: '[图片]',
+ time: '昨天',
+ unread: 0,
+ },
+
+ // === 骑手对话 ===
+ {
+ id: 'chat4',
+ type: 'chat',
+ avatar: 'https://picsum.photos/seed/rider1/100/100',
+ name: '骑手-刘师傅',
+ role: 'rider',
+ lastMessage: '好的,快递已取到,预计15分钟送到北门,请准时来取',
+ time: '11:20',
+ unread: 2,
+ online: false,
+ },
+ {
+ id: 'chat5',
+ type: 'chat',
+ avatar: 'https://picsum.photos/seed/rider2/100/100',
+ name: '骑手-陈师傅',
+ role: 'rider',
+ lastMessage: '同学你好,我已经到楼下了,你下来拿一下吧',
+ time: '昨天',
+ unread: 0,
+ online: true,
+ },
+
+ // === 商家对话 ===
+ {
+ id: 'chat6',
+ type: 'chat',
+ avatar: 'https://picsum.photos/seed/merchant1/100/100',
+ name: '校园咖啡馆',
+ role: 'merchant',
+ lastMessage: '您的拿铁已经做好了,请来取餐,谢谢!',
+ time: '08:45',
+ unread: 0,
+ online: true,
+ },
+ {
+ id: 'chat7',
+ type: 'chat',
+ avatar: 'https://picsum.photos/seed/merchant2/100/100',
+ name: '二手书店',
+ role: 'merchant',
+ lastMessage: '那本数据结构还有货,可以来店里看看,西门旁边',
+ time: '周一',
+ unread: 1,
+ },
+]
diff --git a/src/mock/tasks.ts b/src/mock/tasks.ts
new file mode 100644
index 0000000..ffb6afd
--- /dev/null
+++ b/src/mock/tasks.ts
@@ -0,0 +1,133 @@
+import type { Task } from '@/types/task'
+
+export const tasks: Task[] = [
+ // === 快递代取 ===
+ {
+ id: 't1',
+ type: 'express',
+ title: '帮我取个快递,菜鸟驿站3号柜',
+ desc: '中通快递,小件包裹,就在南区菜鸟驿站3号柜,取件码已发你',
+ reward: '¥5.00',
+ location: '南区菜鸟驿站',
+ time: '10分钟前',
+ status: 'open',
+ publisher: { name: '李同学', avatar: 'https://picsum.photos/seed/u1/100/100' },
+ deadline: '今天 18:00 前',
+ },
+ {
+ id: 't2',
+ type: 'express',
+ title: '顺丰快递代取,北门快递点',
+ desc: '顺丰快递一个,较大件(鞋盒大小),北门快递柜,需今天内取',
+ reward: '¥8.00',
+ location: '北门快递柜',
+ time: '25分钟前',
+ status: 'open',
+ publisher: { name: '王同学', avatar: 'https://picsum.photos/seed/u2/100/100' },
+ deadline: '今天 20:00 前',
+ },
+
+ // === 二手交易 ===
+ {
+ id: 't3',
+ type: 'secondhand',
+ title: '出手99新 iPad Air 5,带Apple Pencil',
+ desc: '去年购入,使用不到半年,无拆无修,电池健康度95%,256G深空灰',
+ reward: '¥3200',
+ location: '东区宿舍',
+ time: '1小时前',
+ status: 'open',
+ publisher: { name: '赵同学', avatar: 'https://picsum.photos/seed/u3/100/100' },
+ images: [
+ 'https://picsum.photos/seed/ipad1/200/200',
+ 'https://picsum.photos/seed/ipad2/200/200',
+ ],
+ tags: ['数码', '99新', '在保'],
+ },
+ {
+ id: 't4',
+ type: 'secondhand',
+ title: '二手教材出售:高等数学+线性代数',
+ desc: '大一教材,几乎全新,笔记很少,两本一起出',
+ reward: '¥30',
+ location: '西区图书馆',
+ time: '3小时前',
+ status: 'open',
+ publisher: { name: '陈同学', avatar: 'https://picsum.photos/seed/u4/100/100' },
+ images: ['https://picsum.photos/seed/book/200/200'],
+ tags: ['教材', '大一'],
+ },
+
+ // === 求助信息 ===
+ {
+ id: 't5',
+ type: 'help',
+ title: '找一位计算机学院的同学帮忙辅导数据结构',
+ desc: '期末考试在即,希望找一位数据结构学得好的同学辅导,2小时左右,奶茶酬谢',
+ reward: '¥50/次',
+ location: '图书馆自习室',
+ time: '2小时前',
+ status: 'open',
+ publisher: { name: '刘同学', avatar: 'https://picsum.photos/seed/u5/100/100' },
+ tags: ['学习辅导', '数据结构'],
+ },
+ {
+ id: 't6',
+ type: 'help',
+ title: '帮忙搬宿舍,男生,从南区搬到北区',
+ desc: '暑假宿舍调整,需要搬运行李,东西不多,大概1小时能搞定',
+ reward: '¥30',
+ location: '南→北宿舍区',
+ time: '1小时前',
+ status: 'progress',
+ publisher: { name: '周同学', avatar: 'https://picsum.photos/seed/u6/100/100' },
+ tags: ['搬运', '急'],
+ },
+
+ // === 校园活动 ===
+ {
+ id: 't7',
+ type: 'activity',
+ title: '周末桌游局,缺2人,狼人杀/阿瓦隆',
+ desc: '周六下午2点,学校咖啡厅,已有8人,再找2个小伙伴一起玩',
+ reward: '免费',
+ location: '校内咖啡厅',
+ time: '3小时前',
+ status: 'open',
+ publisher: { name: '吴同学', avatar: 'https://picsum.photos/seed/u7/100/100' },
+ participants: 8,
+ maxParticipants: 10,
+ tags: ['桌游', '周末', '社交'],
+ },
+ {
+ id: 't8',
+ type: 'activity',
+ title: '校园夜跑团招新,每周二四六晚8点',
+ desc: '欢迎喜欢跑步的同学加入,各种配速都有,一起锻炼身体',
+ reward: '免费',
+ location: '田径场',
+ time: '5小时前',
+ status: 'open',
+ publisher: { name: '跑步社团', avatar: 'https://picsum.photos/seed/u8/100/100' },
+ participants: 35,
+ maxParticipants: 100,
+ tags: ['运动', '跑步', '社团'],
+ },
+
+ // === 拼车出行 ===
+ {
+ id: 't9',
+ type: 'carpool',
+ title: '周五下午去市中心,有车,还有3个空位',
+ desc: '周五下午4点出发,可以到市中心任意地点,有车的同学顺路带人',
+ reward: '¥15/人',
+ location: '学校南门出发',
+ time: '30分钟前',
+ status: 'open',
+ publisher: { name: '郑同学', avatar: 'https://picsum.photos/seed/u9/100/100' },
+ deadline: '周五 16:00',
+ participants: 1,
+ maxParticipants: 4,
+ tags: ['拼车', '周五', '市中心'],
+ },
+]
diff --git a/src/pages/messages/index.less b/src/pages/messages/index.less
index 64f76aa..d0dcfad 100644
--- a/src/pages/messages/index.less
+++ b/src/pages/messages/index.less
@@ -1,29 +1,165 @@
+/* ========================================
+ 消息页面
+ ======================================== */
+
.messages-page {
min-height: 100vh;
+ display: flex;
+ flex-direction: column;
background: #f7f8fa;
+}
- .page-placeholder {
+.messages-scroll {
+ flex: 1;
+}
+
+/* ========== 分区 ========== */
+.section-block {
+ margin: 20px 24px 0;
+ background: #fff;
+ border-radius: 16px;
+ overflow: hidden;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
+
+ .section-title {
+ font-size: 28px;
+ font-weight: 500;
+ color: #323233;
+ padding: 24px 24px 12px;
+ }
+}
+
+/* ========== 消息列表项 ========== */
+.message-item {
+ display: flex;
+ align-items: center;
+ padding: 24px;
+ transition: background 0.15s;
+
+ &:active {
+ background: #f7f8fa;
+ }
+
+ & + .message-item {
+ border-top: 1px solid #f2f3f5;
+ }
+}
+
+/* ========== 系统消息 ========== */
+.system-msg {
+ .sys-icon {
+ width: 88px;
+ height: 88px;
+ border-radius: 50%;
+ background: linear-gradient(135deg, #1989fa 0%, #07c160 100%);
+ color: #fff;
+ font-size: 36px;
display: flex;
- flex-direction: column;
align-items: center;
justify-content: center;
- padding-top: 300px;
+ flex-shrink: 0;
+ }
- .placeholder-icon {
- font-size: 96px;
- margin-bottom: 24px;
+ .pinned-tag {
+ font-size: 20px;
+ color: #1989fa;
+ background: #e8f4ff;
+ padding: 4px 10px;
+ border-radius: 4px;
+ flex-shrink: 0;
+ align-self: flex-start;
+ margin-top: 4px;
+ }
+}
+
+/* ========== 聊天消息 ========== */
+.chat-msg {
+ .avatar-wrap {
+ position: relative;
+ flex-shrink: 0;
+
+ .msg-avatar {
+ width: 96px;
+ height: 96px;
+ border-radius: 50%;
}
- .placeholder-text {
- font-size: 36px;
- font-weight: 500;
- color: #323233;
- margin-bottom: 12px;
- }
-
- .placeholder-desc {
- font-size: 28px;
- color: #969799;
+ .online-dot {
+ position: absolute;
+ bottom: 2px;
+ right: 2px;
+ width: 18px;
+ height: 18px;
+ border-radius: 50%;
+ background: #07c160;
+ border: 3px solid #fff;
}
}
}
+
+/* ========== 消息内容区 ========== */
+.msg-body {
+ flex: 1;
+ margin-left: 20px;
+ overflow: hidden;
+
+ .msg-top {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+
+ .msg-name-row {
+ display: flex;
+ align-items: center;
+ }
+
+ .msg-name {
+ font-size: 30px;
+ font-weight: 500;
+ color: #1a1a1a;
+ }
+
+ .msg-time {
+ font-size: 22px;
+ color: #c8c9cc;
+ flex-shrink: 0;
+ }
+ }
+
+ .msg-preview {
+ font-size: 26px;
+ color: #969799;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: block;
+ }
+}
+
+/* ========== 角色标签 ========== */
+.role-tag {
+ font-size: 20px;
+ padding: 2px 8px;
+ border-radius: 4px;
+ margin-left: 10px;
+
+ &.role-rider {
+ background: #fff3e8;
+ color: #ff976a;
+ }
+
+ &.role-merchant {
+ background: #e8f4ff;
+ color: #1989fa;
+ }
+
+ &.role-user {
+ background: #f2f3f5;
+ color: #646566;
+ }
+}
+
+.bottom-safe {
+ height: 20px;
+}
diff --git a/src/pages/messages/index.tsx b/src/pages/messages/index.tsx
index eaf26eb..a12fbc9 100644
--- a/src/pages/messages/index.tsx
+++ b/src/pages/messages/index.tsx
@@ -1,15 +1,100 @@
-import { View, Text } from '@tarojs/components'
-import CustomTabBar from "@/custom-tab-bar"
+import Taro from '@tarojs/taro'
+import { View, Text, Image, ScrollView } from '@tarojs/components'
+import { Badge } from '@antmjs/vantui'
+import CustomTabBar from '@/custom-tab-bar'
+import { chatList } from '@/mock/messages'
+import type { ChatItem } from '@/types/message'
import './index.less'
+/** 角色标签 */
+const ROLE_LABEL: Record = {
+ rider: { text: '骑手', className: 'role-rider' },
+ merchant: { text: '商家', className: 'role-merchant' },
+ user: { text: '同学', className: 'role-user' },
+}
+
export default function Messages() {
+ const handleChatClick = (item: ChatItem) => {
+ Taro.showToast({ title: `${item.name || item.title} 聊天即将上线`, icon: 'none' })
+ }
+
+ // 分组:置顶系统消息 + 普通聊天
+ const systemMsgs = chatList.filter((m) => m.type === 'system')
+ const chatMsgs = chatList.filter((m) => m.type === 'chat')
+
return (
-
- 💬
- 消息
- 即将上线,敬请期待
-
+
+ {/* ========== 置顶系统消息 ========== */}
+ {systemMsgs.length > 0 && (
+
+ 系统消息
+ {systemMsgs.map((msg) => (
+ handleChatClick(msg)}
+ >
+ {msg.title.slice(0, 2)}
+
+
+ {msg.title}
+ {msg.time}
+
+ {msg.content}
+
+ {msg.pinned && 置顶}
+
+ ))}
+
+ )}
+
+ {/* ========== 聊天消息 ========== */}
+
+ 聊天消息
+ {chatMsgs.map((msg) => (
+ handleChatClick(msg)}
+ >
+ {/* 头像 */}
+
+
+ {msg.online && }
+
+
+ {/* 消息内容 */}
+
+
+
+ {msg.name}
+ {msg.role && (
+
+ {ROLE_LABEL[msg.role]?.text || ''}
+
+ )}
+
+ {msg.time}
+
+ {msg.lastMessage}
+
+
+ {/* 未读数 */}
+ {msg.unread ? (
+
+ ) : null}
+
+ ))}
+
+
+
+
+
)
diff --git a/src/pages/profile/index.less b/src/pages/profile/index.less
index c66ca7b..09ea606 100644
--- a/src/pages/profile/index.less
+++ b/src/pages/profile/index.less
@@ -1,29 +1,229 @@
+/* ========================================
+ 个人中心页面
+ ======================================== */
+
.profile-page {
min-height: 100vh;
background: #f7f8fa;
+}
- .page-placeholder {
+/* ========== 顶部背景区域 ========== */
+.profile-header {
+ position: relative;
+ background: linear-gradient(160deg, #1989fa 0%, #07c160 100%);
+ padding-bottom: 32px;
+ overflow: hidden;
+
+ /* 背景装饰圆 */
+ &::before {
+ content: '';
+ position: absolute;
+ top: -80px;
+ right: -60px;
+ width: 280px;
+ height: 280px;
+ border-radius: 50%;
+ background: rgba(255, 255, 255, 0.08);
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ bottom: -40px;
+ left: -40px;
+ width: 200px;
+ height: 200px;
+ border-radius: 50%;
+ background: rgba(255, 255, 255, 0.05);
+ }
+}
+
+/* 设置按钮 */
+.header-actions {
+ display: flex;
+ justify-content: flex-end;
+ padding: 12px 24px 0;
+
+ .settings-btn {
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ background: rgba(255, 255, 255, 0.15);
+ backdrop-filter: blur(10px);
+ }
+}
+
+/* 用户卡片 */
+.user-card {
+ display: flex;
+ align-items: center;
+ padding: 24px 32px 20px;
+ position: relative;
+ z-index: 1;
+
+ .avatar {
+ width: 120px;
+ height: 120px;
+ border-radius: 50%;
+ border: 4px solid rgba(255, 255, 255, 0.4);
+ flex-shrink: 0;
+ }
+
+ .user-info {
+ flex: 1;
+ margin-left: 24px;
+
+ .name-row {
+ display: flex;
+ align-items: center;
+ margin-bottom: 8px;
+
+ .name {
+ font-size: 40px;
+ font-weight: 600;
+ color: #fff;
+ margin-right: 12px;
+ }
+
+ .gender-tag {
+ font-size: 22px;
+ width: 36px;
+ height: 36px;
+ line-height: 36px;
+ text-align: center;
+ border-radius: 50%;
+ background: rgba(255, 255, 255, 0.25);
+ color: #fff;
+ }
+ }
+
+ .class-name {
+ font-size: 26px;
+ color: rgba(255, 255, 255, 0.8);
+ }
+ }
+
+ .van-icon {
+ flex-shrink: 0;
+ }
+}
+
+/* 点赞/评论/收藏 */
+.stats-row {
+ display: flex;
+ justify-content: space-around;
+ padding: 0 32px;
+ position: relative;
+ z-index: 1;
+
+ .stat-item {
display: flex;
flex-direction: column;
align-items: center;
- justify-content: center;
- padding-top: 300px;
- .placeholder-icon {
- font-size: 96px;
- margin-bottom: 24px;
- }
-
- .placeholder-text {
+ .stat-num {
font-size: 36px;
- font-weight: 500;
- color: #323233;
- margin-bottom: 12px;
+ font-weight: 600;
+ color: #fff;
+ line-height: 1.4;
}
- .placeholder-desc {
- font-size: 28px;
- color: #969799;
+ .stat-label {
+ font-size: 24px;
+ color: rgba(255, 255, 255, 0.75);
}
}
}
+
+/* ========== 滚动内容 ========== */
+.profile-scroll {
+ height: calc(100vh - 100px);
+}
+
+/* ========== 通用卡片 ========== */
+.section-card {
+ margin: 20px 24px;
+ background: #fff;
+ border-radius: 16px;
+ overflow: hidden;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
+
+ .card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 28px 24px 20px;
+
+ .card-title {
+ font-size: 32px;
+ font-weight: 500;
+ color: #323233;
+ }
+
+ .card-more {
+ display: flex;
+ align-items: center;
+
+ .more-text {
+ font-size: 26px;
+ color: #969799;
+ margin-right: 4px;
+ }
+ }
+ }
+}
+
+/* ========== 订单区域 ========== */
+.order-tabs {
+ display: flex;
+ justify-content: space-around;
+ padding: 0 8px 28px;
+
+ .order-tab {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 12px 8px;
+
+ .tab-label {
+ font-size: 24px;
+ color: #646566;
+ margin-top: 10px;
+ }
+ }
+}
+
+/* ========== 功能列表 ========== */
+.feature-list {
+ margin-top: 20px;
+
+ .van-cell-group--inset {
+ margin: 0;
+ }
+
+ .van-cell {
+ padding: 28px 24px;
+ }
+}
+
+/* ========== 底部信息 ========== */
+.footer-info {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 40px 0 20px;
+
+ .footer-icp {
+ font-size: 22px;
+ color: #c8c9cc;
+ margin-bottom: 8px;
+ }
+
+ .footer-version {
+ font-size: 22px;
+ color: #c8c9cc;
+ }
+}
diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx
index 78d114a..221ae66 100644
--- a/src/pages/profile/index.tsx
+++ b/src/pages/profile/index.tsx
@@ -1,15 +1,162 @@
-import { View, Text } from '@tarojs/components'
-import CustomTabBar from "@/custom-tab-bar"
+import { useMemo } from 'react'
+import Taro from '@tarojs/taro'
+import { View, Text, Image, ScrollView } from '@tarojs/components'
+import { Cell, CellGroup, Icon } from '@antmjs/vantui'
+import CustomTabBar from '@/custom-tab-bar'
import './index.less'
+/** 状态栏高度 */
+function getStatusBarHeight(): number {
+ try {
+ return Taro.getSystemInfoSync().statusBarHeight || 20
+ } catch {
+ return 20
+ }
+}
+
+/** 用户信息(后续接入 API) */
+const USER_INFO = {
+ avatar: 'https://picsum.photos/seed/avatar/200/200',
+ name: '张三',
+ className: '计算机科学与技术 2022级',
+ gender: '男' as const,
+ stats: { likes: 128, comments: 46, favorites: 89 },
+}
+
+/** 订单入口 */
+const ORDER_TABS = [
+ { key: 'all', label: '全部', icon: 'orders-o' },
+ { key: 'pending', label: '待付款', icon: 'balance-pay' },
+ { key: 'progress', label: '进行中', icon: 'logistics' },
+ { key: 'confirm', label: '待确认', icon: 'checked' },
+ { key: 'review', label: '待评价', icon: 'star-o' },
+]
+
+/** 功能列表 */
+const FEATURE_LIST = [
+ { key: 'goods', label: '商品订单', icon: 'orders-o' },
+ { key: 'address', label: '地址管理', icon: 'location-o' },
+ { key: 'about', label: '关于我们', icon: 'info-o' },
+ { key: 'feedback', label: '意见反馈', icon: 'chat-o' },
+ { key: 'settings', label: '系统设置', icon: 'setting-o' },
+] as const
+
export default function Profile() {
+ const statusBarH = useMemo(getStatusBarHeight, [])
+
+ const handleSettings = () => {
+ Taro.showToast({ title: '设置页面即将上线', icon: 'none' })
+ }
+
+ const handleEditProfile = () => {
+ Taro.showToast({ title: '编辑资料即将上线', icon: 'none' })
+ }
+
+ const handleOrderTab = (key: string) => {
+ Taro.showToast({ title: `${ORDER_TABS.find(t => t.key === key)?.label || ''}订单即将上线`, icon: 'none' })
+ }
+
+ const handleFeature = (item: typeof FEATURE_LIST[number]) => {
+ Taro.showToast({ title: `${item.label}即将上线`, icon: 'none' })
+ }
+
+ const handleAllOrders = () => {
+ Taro.showToast({ title: '全部订单即将上线', icon: 'none' })
+ }
+
return (
-
- 👤
- 我的
- 即将上线,敬请期待
+ {/* ========== 背景图区域 ========== */}
+
+ {/* 设置按钮 */}
+
+
+
+
+
+
+ {/* 头像 + 用户信息 */}
+
+
+
+
+ {USER_INFO.name}
+ {USER_INFO.gender === '男' ? '♂' : '♀'}
+
+ {USER_INFO.className}
+
+
+
+
+ {/* 点赞/评论/收藏 */}
+
+
+ {USER_INFO.stats.likes}
+ 点赞
+
+
+ {USER_INFO.stats.comments}
+ 评论
+
+
+ {USER_INFO.stats.favorites}
+ 收藏
+
+
+
+ {/* ========== 可滚动内容 ========== */}
+
+ {/* ========== 订单卡片 ========== */}
+
+
+ 我的订单
+
+ 全部
+
+
+
+
+ {ORDER_TABS.map((tab) => (
+ handleOrderTab(tab.key)}
+ >
+
+ {tab.label}
+
+ ))}
+
+
+
+ {/* ========== 功能列表 ========== */}
+
+
+ {FEATURE_LIST.map((item, index) => (
+ | handleFeature(item)}
+ />
+ ))}
+ |
+
+
+ {/* ========== 底部信息 ========== */}
+
+ 湘ICP备2024000000号-1
+ 校园通 v1.0.0
+
+
+
+ {/* ========== TabBar ========== */}
)
diff --git a/src/pages/tasks/index.less b/src/pages/tasks/index.less
index c26d7f5..6e2b9f7 100644
--- a/src/pages/tasks/index.less
+++ b/src/pages/tasks/index.less
@@ -1,29 +1,97 @@
+/* ========================================
+ 校园任务页面
+ ======================================== */
+
.tasks-page {
min-height: 100vh;
+ display: flex;
+ flex-direction: column;
background: #f7f8fa;
+}
- .page-placeholder {
+/* 搜索栏 */
+.tasks-search-bar {
+ padding: 20px 24px;
+ background: #fff;
+}
+
+/* 分类筛选 */
+.tasks-filter {
+ background: #fff;
+ padding-bottom: 16px;
+
+ .filter-scroll {
+ white-space: nowrap;
+ }
+
+ .filter-tabs {
+ display: flex;
+ padding: 0 24px;
+ gap: 12px;
+ }
+
+ .filter-tab {
display: flex;
flex-direction: column;
align-items: center;
- justify-content: center;
- padding-top: 300px;
+ padding: 16px 20px;
+ border-radius: 16px;
+ background: #f7f8fa;
+ flex-shrink: 0;
+ min-width: 120px;
+ transition: all 0.2s;
- .placeholder-icon {
- font-size: 96px;
- margin-bottom: 24px;
+ &.active {
+ background: #1989fa;
+ box-shadow: 0 4px 16px rgba(25, 137, 250, 0.3);
+
+ .filter-emoji {
+ transform: scale(1.1);
+ }
+
+ .filter-label {
+ color: #fff;
+ }
}
- .placeholder-text {
+ .filter-emoji {
font-size: 36px;
- font-weight: 500;
- color: #323233;
- margin-bottom: 12px;
+ margin-bottom: 6px;
+ transition: transform 0.2s;
}
- .placeholder-desc {
- font-size: 28px;
- color: #969799;
+ .filter-label {
+ font-size: 24px;
+ color: #646566;
}
}
}
+
+/* 任务列表 */
+.tasks-scroll {
+ flex: 1;
+}
+
+.tasks-list {
+ padding: 16px 24px;
+
+ .task-card-wrap {
+ margin-bottom: 16px;
+ transition: transform 0.2s;
+
+ &:active {
+ transform: scale(0.98);
+ }
+ }
+
+ .empty-tip {
+ text-align: center;
+ padding: 120px 0;
+ font-size: 28px;
+ color: #969799;
+ }
+}
+
+.bottom-safe {
+ height: 20px;
+}
diff --git a/src/pages/tasks/index.tsx b/src/pages/tasks/index.tsx
index bb99826..f03a19e 100644
--- a/src/pages/tasks/index.tsx
+++ b/src/pages/tasks/index.tsx
@@ -1,15 +1,106 @@
-import { View, Text } from '@tarojs/components'
-import CustomTabBar from "@/custom-tab-bar"
+import { useState, useMemo } from 'react'
+import Taro from '@tarojs/taro'
+import { View, ScrollView } from '@tarojs/components'
+import { Search, Tabs, Tab } from '@antmjs/vantui'
+import TaskCard from '@/components/TaskCard'
+import CustomTabBar from '@/custom-tab-bar'
+import { tasks } from '@/mock/tasks'
+import type { TaskType } from '@/types/task'
import './index.less'
+/** 筛选标签 */
+const FILTER_TABS = [
+ { title: '全部', value: 'all' as const },
+ { title: '快递代取', value: 'express' as const },
+ { title: '二手交易', value: 'secondhand' as const },
+ { title: '求助', value: 'help' as const },
+ { title: '活动', value: 'activity' as const },
+ { title: '拼车', value: 'carpool' as const },
+]
+
+/** 任务类型 → emoji */
+const TYPE_EMOJI: Record = {
+ all: '📋',
+ express: '📦',
+ secondhand: '🛍️',
+ help: '🆘',
+ activity: '🎉',
+ carpool: '🚗',
+}
+
export default function Tasks() {
+ const [activeFilter, setActiveFilter] = useState(0)
+ const [searchValue, setSearchValue] = useState('')
+
+ const filteredTasks = useMemo(() => {
+ const filterValue = FILTER_TABS[activeFilter]?.value || 'all'
+ let list = filterValue === 'all' ? tasks : tasks.filter((t) => t.type === filterValue)
+ if (searchValue.trim()) {
+ const kw = searchValue.trim().toLowerCase()
+ list = list.filter(
+ (t) =>
+ t.title.toLowerCase().includes(kw) ||
+ t.desc.toLowerCase().includes(kw) ||
+ t.location.toLowerCase().includes(kw),
+ )
+ }
+ return list
+ }, [activeFilter, searchValue])
+
+ const handleTaskClick = (id: string) => {
+ Taro.showToast({ title: '任务详情即将上线', icon: 'none' })
+ }
+
return (
-
- 📋
- 校园任务
- 即将上线,敬请期待
+ {/* 搜索栏 */}
+
+ setSearchValue(e.detail)}
+ onClear={() => setSearchValue('')}
+ />
+
+ {/* 分类标签 */}
+
+
+
+ {FILTER_TABS.map((tab, idx) => (
+ setActiveFilter(idx)}
+ >
+ {TYPE_EMOJI[tab.value]}
+ {tab.title}
+
+ ))}
+
+
+
+
+ {/* 任务列表 */}
+
+
+ {filteredTasks.map((task) => (
+ handleTaskClick(task.id)}
+ >
+
+
+ ))}
+ {filteredTasks.length === 0 && (
+ 暂无相关任务
+ )}
+
+
+
+
)
diff --git a/src/types/message.ts b/src/types/message.ts
new file mode 100644
index 0000000..bf0c584
--- /dev/null
+++ b/src/types/message.ts
@@ -0,0 +1,25 @@
+/** 消息相关类型 */
+
+/** 消息类型 */
+export type MessageType = 'system' | 'chat'
+
+/** 聊天对象类型 */
+export type ChatRole = 'user' | 'rider' | 'merchant'
+
+/** 聊天消息项 */
+export interface ChatItem {
+ id: string
+ type: MessageType
+ /** 系统消息 */
+ title: string
+ content: string
+ time: string
+ /** 聊天消息 */
+ avatar?: string
+ name?: string
+ role?: ChatRole
+ lastMessage?: string
+ unread?: number
+ pinned?: boolean // 置顶
+ online?: boolean // 在线状态
+}
diff --git a/src/types/task.ts b/src/types/task.ts
new file mode 100644
index 0000000..3a6b038
--- /dev/null
+++ b/src/types/task.ts
@@ -0,0 +1,28 @@
+/** 校园任务相关类型 */
+
+/** 任务类型 */
+export type TaskType = 'express' | 'secondhand' | 'help' | 'activity' | 'carpool'
+
+/** 任务状态 */
+export type TaskStatus = 'open' | 'progress' | 'done' | 'cancelled'
+
+/** 任务数据 */
+export interface Task {
+ id: string
+ type: TaskType
+ title: string
+ desc: string
+ reward: string // 报酬/价格,如 "¥5.00"、"免费"
+ location: string // 地点
+ time: string // 发布时间
+ status: TaskStatus
+ publisher: {
+ name: string
+ avatar: string
+ }
+ tags?: string[] // 标签
+ images?: string[] // 图片(二手/活动类)
+ deadline?: string // 截止时间
+ participants?: number // 参与人数(活动类)
+ maxParticipants?: number
+}