项目初始化

This commit is contained in:
2025-08-09 17:41:14 +08:00
parent a35ecb09f3
commit 7e60227aa6
24 changed files with 1103 additions and 60 deletions

View File

@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@@ -0,0 +1,8 @@
Component({
data: {
},
methods: {
},
})

View File

@@ -0,0 +1,95 @@
<view class="message-container">
<!-- 搜索栏 -->
<view class="search-bar">
<view class="search-input">
<icon type="search" size="16" color="#999"></icon>
<input placeholder="搜索聊天记录" placeholder-class="placeholder-style"/>
</view>
</view>
<!-- 消息列表 - 不按日期分组 -->
<scroll-view class="message-list" scroll-y>
<!-- 消息项1 - 个人聊天(有未读) -->
<view class="message-item" bindtap="goToChat">
<view class="avatar-container">
<image class="avatar" src="https://picsum.photos/id/64/200/200" mode="cover"></image>
<view class="unread-dot"></view>
</view>
<view class="message-content">
<view class="content-top">
<text class="username">王小明</text>
<text class="time">10:23</text>
</view>
<view class="content-bottom">
<text class="last-message">我们明天上午9点在公司楼下集合吧</text>
</view>
</view>
</view>
<!-- 消息项2 - 群聊 -->
<view class="message-item" bindtap="goToChat">
<view class="avatar-container">
<image class="avatar" src="https://picsum.photos/id/26/200/200" mode="cover"></image>
</view>
<view class="message-content">
<view class="content-top">
<text class="username">产品研发群</text>
<text class="time">昨天</text>
</view>
<view class="content-bottom">
<text class="last-message"><text class="sender">李设计</text>新的UI稿已经上传到群文件了</text>
</view>
</view>
</view>
<!-- 消息项3 - 系统通知 -->
<view class="message-item" bindtap="goToChat">
<view class="avatar-container">
<image class="avatar" src="https://picsum.photos/id/91/200/200" mode="cover"></image>
<view class="unread-count">3</view>
</view>
<view class="message-content">
<view class="content-top">
<text class="username">系统通知</text>
<text class="time">周一</text>
</view>
<view class="content-bottom">
<text class="last-message">您有3条新的系统通知待查看</text>
</view>
</view>
</view>
<!-- 消息项4 - 个人聊天 -->
<view class="message-item" bindtap="goToChat">
<view class="avatar-container">
<image class="avatar" src="https://picsum.photos/id/65/200/200" mode="cover"></image>
</view>
<view class="message-content">
<view class="content-top">
<text class="username">张小红</text>
<text class="time">09-12</text>
</view>
<view class="content-bottom">
<text class="last-message">上次你说的那个电影资源能发我一下吗?</text>
</view>
</view>
</view>
<!-- 消息项5 - 服务号消息 -->
<view class="message-item" bindtap="goToChat">
<view class="avatar-container">
<image class="avatar" src="https://picsum.photos/id/62/200/200" mode="cover"></image>
</view>
<view class="message-content">
<view class="content-top">
<text class="username">生活服务号</text>
<text class="time">09-10</text>
</view>
<view class="content-bottom">
<text class="last-message">您订阅的服务已更新,点击查看详情</text>
</view>
</view>
</view>
</scroll-view>
</view>

View File

@@ -0,0 +1,149 @@
/* 消息列表容器 */
.message-container {
background-color: #f5f5f7;
min-height: 100vh;
}
/* 搜索栏样式 */
.search-bar {
padding: 16rpx 24rpx;
background-color: #f5f5f7;
}
.search-input {
display: flex;
align-items: center;
background-color: #eaeaea;
border-radius: 30rpx;
padding: 14rpx 24rpx;
}
.search-input input {
margin-left: 12rpx;
font-size: 28rpx;
flex: 1;
color: #333;
height: 40rpx;
line-height: 40rpx;
}
.placeholder-style {
color: #999;
}
/* 消息列表滚动区域 */
.message-list {
height: calc(100vh - 96rpx); /* 减去搜索栏高度 */
width: 100%;
}
/* 消息项样式 - 已调整高度 */
.message-item {
display: flex;
padding: 16rpx 24rpx; /* 减少内边距 */
background-color: #fff;
border-bottom: 1rpx solid #f1f1f1;
align-items: center;
transition: background-color 0.2s;
height: 120rpx; /* 固定消息项高度 */
}
.message-item:active {
background-color: #f5f5f5;
}
/* 头像容器 */
.avatar-container {
position: relative;
margin-right: 20rpx;
}
/* 头像样式 - 缩小尺寸 */
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 16rpx;
}
/* 未读提示 */
.unread-dot {
position: absolute;
right: 0;
top: 0;
width: 24rpx;
height: 24rpx;
background-color: #ff4d4f;
border-radius: 50%;
border: 4rpx solid #fff;
}
/* 未读数量 */
.unread-count {
position: absolute;
right: 0;
top: 0;
min-width: 28rpx;
height: 28rpx;
line-height: 28rpx;
background-color: #ff4d4f;
border-radius: 14rpx;
border: 4rpx solid #fff;
color: #fff;
font-size: 20rpx;
text-align: center;
padding: 0 8rpx;
}
/* 消息内容区域 */
.message-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
overflow: hidden;
}
/* 内容顶部(用户名和时间) */
.content-top {
display: flex;
justify-content: space-between;
margin-bottom: 6rpx; /* 减少间距 */
}
.username {
font-size: 30rpx;
color: #333;
font-weight: 500;
max-width: 400rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.time {
font-size: 24rpx;
color: #999;
}
/* 内容底部(最后一条消息) */
.content-bottom {
display: flex;
justify-content: space-between;
align-items: center;
}
.last-message {
font-size: 26rpx; /* 缩小字体 */
color: #666;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
flex: 1;
}
/* 群聊消息中的发送者 */
.sender {
color: #677fff;
margin-right: 4rpx;
}

View File

@@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"t-divider": "tdesign-miniprogram/divider/divider",
"t-search": "tdesign-miniprogram/search/search"
}
}

View File

@@ -0,0 +1,8 @@
Component({
data: {
},
methods: {
},
})

View File

@@ -0,0 +1,112 @@
<view class="search-bar">
<view class="search-input">
<icon type="search" size="16" color="#999"></icon>
<input placeholder="搜索聊天记录" placeholder-class="placeholder-style"/>
</view>
</view>
<view style="width: 100vw;display: flex;justify-content: center;">
<view class="voting-card">
<!-- 卡片头部 -->
<view class="card-header">
<view class="user-info">
<image src="https://picsum.photos/id/64/200/200" mode="widthFix" class="avatar" alt="发起者头像"></image>
<view class="user-details">
<text class="username">张小萌</text>
<text class="user-status">需要你的帮助</text>
</view>
</view>
<view class="vote-status">进行中</view>
</view>
<view class="divider"></view>
<view class="vote-title-section">
<text class="vote-title">午餐该选哪个?好纠结啊!</text>
<text class="vote-desc">大家帮我投个票吧,选择困难症又犯了...</text>
</view>
<!-- 选项区域 -->
<view class="options-container">
<!-- 选项1 -->
<view class="option-item {{selectedOption === '1' ? 'selected' : ''}}" bindtap="selectOption" data-id="1">
<view class="option-info">
<view class="option-icon bg-red">
<text class="iconfont icon-cutlery"></text>
</view>
<view class="option-details">
<text class="option-name">麻辣烫</text>
<text class="option-desc">鲜香麻辣,越吃越开胃</text>
</view>
</view>
<text class="option-percent">42%</text>
<view class="progress-bar">
<view class="progress-value" style="width: 42%"></view>
</view>
<view class="vote-indicator {{selectedOption === '1' ? 'show' : ''}}">
<text class="iconfont icon-check-circle"></text>
</view>
</view>
<!-- 选项2 -->
<view class="option-item {{selectedOption === '2' ? 'selected' : ''}}" bindtap="selectOption" data-id="2">
<view class="option-info">
<view class="option-icon bg-yellow">
<text class="iconfont icon-coffee"></text>
</view>
<view class="option-details">
<text class="option-name">汉堡套餐</text>
<text class="option-desc">快捷方便,配冰可乐</text>
</view>
</view>
<text class="option-percent">28%</text>
<view class="progress-bar">
<view class="progress-value" style="width: 28%"></view>
</view>
<view class="vote-indicator {{selectedOption === '2' ? 'show' : ''}}">
<text class="iconfont icon-check-circle"></text>
</view>
</view>
<!-- 选项3 -->
<view class="option-item {{selectedOption === '3' ? 'selected' : ''}}" bindtap="selectOption" data-id="3">
<view class="option-info">
<view class="option-icon bg-green">
<text class="iconfont icon-leaf"></text>
</view>
<view class="option-details">
<text class="option-name">沙拉轻食</text>
<text class="option-desc">健康低卡,适合减脂</text>
</view>
</view>
<text class="option-percent">30%</text>
<view class="progress-bar">
<view class="progress-value" style="width: 30%"></view>
</view>
<view class="vote-indicator {{selectedOption === '3' ? 'show' : ''}}">
<text class="iconfont icon-check-circle"></text>
</view>
</view>
</view>
<view class="vote-stats">
<text class="stats-text">已有 126 人参与投票</text>
<text class="stats-text">剩余 23 小时结束</text>
</view>
<!-- 投票按钮 -->
<button class="vote-btn" bindtap="submitVote">
<text class="iconfont icon-thumbs-up"></text>
<text class="btn-text">投我一票</text>
</button>
</view>
</view>

View File

@@ -0,0 +1,291 @@
/* 引入通用样式 */
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #f5f7fa;
padding: 20rpx;
}
.search-bar {
padding: 16rpx 24rpx;
background-color: #f5f5f7;
}
.search-input {
display: flex;
align-items: center;
background-color: #eaeaea;
border-radius: 30rpx;
padding: 14rpx 24rpx;
}
.search-input input {
margin-left: 12rpx;
font-size: 28rpx;
flex: 1;
color: #333;
height: 40rpx;
line-height: 40rpx;
}
/* 投票卡片卡片样式 */
.voting-card {
width: 90%;
background-color: #ffffff;
border-radius: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
overflow: hidden;
}
/* 卡片头部样式 */
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
}
.user-info {
display: flex;
align-items: center;
}
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.username {
display: block;
font-size: 32rpx;
font-weight: 600;
color: #333333;
margin-bottom: 4rpx;
}
.user-status {
display: block;
font-size: 24rpx;
color: #888888;
}
.vote-status {
background-color: rgba(79, 70, 229, 0.1);
color: #4F46E5;
font-size: 24rpx;
padding: 8rpx 16rpx;
border-radius: 20rpx;
}
.divider {
height: 2rpx;
background-color: #f5f5f5;
}
/* 投票标题区域 */
.vote-title-section {
padding: 0 30rpx 30rpx;
}
.vote-title {
display: block;
font-size: 36rpx;
font-weight: 700;
color: #333333;
margin-bottom: 16rpx;
}
.vote-desc {
font-size: 26rpx;
color: #888888;
}
/* 选项区域样式 */
.options-container {
padding: 0 30rpx 20rpx;
}
.option-item {
position: relative;
padding: 24rpx;
border: 2rpx solid #f0f0f0;
border-radius: 16rpx;
margin-bottom: 20rpx;
transition: all 0.3s;
}
.option-item.selected {
border-color: #4F46E5;
background-color: rgba(79, 70, 229, 0.05);
}
.option-item:hover {
border-color: rgba(79, 70, 229, 0.3);
background-color: rgba(79, 70, 229, 0.03);
}
.option-info {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.option-icon {
width: 64rpx;
height: 64rpx;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 20rpx;
}
.bg-red {
background-color: rgba(248, 113, 113, 0.1);
color: #ef4444;
}
.bg-yellow {
background-color: rgba(251, 191, 36, 0.1);
color: #f59e0b;
}
.bg-green {
background-color: rgba(34, 197, 94, 0.1);
color: #10b981;
}
.option-details {
flex: 1;
}
.option-name {
display: block;
font-size: 30rpx;
font-weight: 600;
color: #333333;
margin-bottom: 4rpx;
}
.option-desc {
font-size: 24rpx;
color: #888888;
}
.option-percent {
font-size: 28rpx;
font-weight: 600;
color: #333333;
}
/* 进度条样式 */
.progress-bar {
height: 12rpx;
background-color: #f0f0f0;
border-radius: 6rpx;
overflow: hidden;
}
.progress-value {
height: 100%;
background-color: #4F46E5;
border-radius: 6rpx;
transition: width 0.5s ease-out;
}
/* 选中指示器 */
.vote-indicator {
position: absolute;
top: 24rpx;
right: 24rpx;
color: #4F46E5;
font-size: 36rpx;
display: none;
}
.vote-indicator.show {
display: block;
}
/* 投票统计信息 */
.vote-stats {
display: flex;
justify-content: space-between;
padding: 0 30rpx 20rpx;
}
.stats-text {
font-size: 24rpx;
color: #888888;
}
/* 投票按钮 */
.vote-btn {
width: calc(100% - 60rpx);
margin: 0 30rpx 30rpx;
padding: 24rpx 0;
background-color: #4F46E5;
color: #ffffff;
border-radius: 16rpx;
font-size: 30rpx;
font-weight: 600;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s;
}
.vote-btn .iconfont {
margin-right: 12rpx;
font-size: 32rpx;
}
.vote-btn::after {
border: none;
}
.vote-btn:hover {
background-color: rgba(79, 70, 229, 0.9);
}
.vote-btn:active {
transform: scale(0.98);
}
/* 成功提示 */
.success-toast {
position: fixed;
top: 50rpx;
left: 50%;
transform: translateX(-50%);
background-color: #10b981;
color: #ffffff;
padding: 16rpx 32rpx;
border-radius: 8rpx;
display: flex;
align-items: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
z-index: 999;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
}
.success-toast.show {
opacity: 1;
pointer-events: auto;
}
.success-toast .iconfont {
margin-right: 12rpx;
font-size: 32rpx;
}
.toast-text {
font-size: 28rpx;
}

View File

@@ -1,5 +1,10 @@
{
"usingComponents": {
"t-button": "tdesign-miniprogram/button/button"
"t-button": "tdesign-miniprogram/button/button",
"t-tab-bar": "tdesign-miniprogram/tab-bar/tab-bar",
"t-tab-bar-item": "tdesign-miniprogram/tab-bar-item/tab-bar-item",
"home-component":"/pages/home/home",
"chat-component":"/pages/chat/chat",
"user-component":"/pages/user/user"
}
}

View File

@@ -1,54 +1,20 @@
// index.ts
// 获取应用实例
const app = getApp<IAppOption>()
const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
Component({
data: {
motto: 'Hello World',
userInfo: {
avatarUrl: defaultAvatarUrl,
nickName: '',
},
hasUserInfo: false,
canIUseGetUserProfile: wx.canIUse('getUserProfile'),
canIUseNicknameComp: wx.canIUse('input.type.nickname'),
label_value: 'label_1',
list: [
{ label_value: 'label_1', icon: 'home', ariaLabel: '首页' },
{ label_value: 'label_2', icon: 'chat', ariaLabel: '聊天' },
{ label_value: 'label_3', icon: 'user', ariaLabel: '我的' },
],
},
methods: {
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs',
})
},
onChooseAvatar(e: any) {
const { avatarUrl } = e.detail
const { nickName } = this.data.userInfo
onChange(e: { detail: { value: any; }; }) {
this.setData({
"userInfo.avatarUrl": avatarUrl,
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
})
},
onInputChange(e: any) {
const nickName = e.detail.value
const { avatarUrl } = this.data.userInfo
this.setData({
"userInfo.nickName": nickName,
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
})
},
getUserProfile() {
// 推荐使用wx.getUserProfile获取用户信息开发者每次通过该接口获取用户个人信息均需用户确认开发者妥善保管用户快速填写的头像昵称避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
label_value: e.detail.value,
});
},
},
})

View File

@@ -1,4 +1,16 @@
<!--index.wxml-->
<scroll-view class="scrollarea" scroll-y type="list">
<t-button theme="primary">按钮</t-button>
<view hidden="{{label_value !== 'label_1'}}"><home-component></home-component></view>
<view hidden="{{label_value !== 'label_2'}}"><chat-component></chat-component></view>
<view hidden="{{label_value !== 'label_3'}}"><user-component></user-component></view>
<t-tab-bar t-class="t-tab-bar" value="{{label_value}}" bindchange="onChange" shape="round" theme="tag" split="{{false}}">
<t-tab-bar-item
wx:for="{{list}}"
wx:key="value"
value="{{item.label_value}}"
icon="{{item.icon}}"
ariaLabel="{{item.ariaLabel}}"
>
</t-tab-bar-item>
</t-tab-bar>
</scroll-view>

View File

@@ -0,0 +1,7 @@
{
"usingComponents": {
"t-button": "tdesign-miniprogram/button/button",
"t-avatar": "tdesign-miniprogram/avatar/avatar",
"t-avatar-group": "tdesign-miniprogram/avatar-group/avatar-group"
}
}

View File

@@ -0,0 +1,37 @@
Component({
data: {
image: 'https://tdesign.gtimg.com/mobile/demos/avatar1.png',
},
methods: {
wxPhone(e: { detail: any; }){
console.log("授权回调结果:", e.detail);
if (e.detail.errMsg === "getPhoneNumber:ok") {
const { encryptedData, iv, code } = e.detail;
wx.request({
url: "http://localhost:9096/user/login",
method: "POST",
data: {
encryptedData,
iv,
code,
},
success(res) {
if (res.data.success) {
// 登录成功,存储用户信息并跳转首页
wx.setStorageSync("userInfo", res.data.userInfo);
wx.navigateTo({ url: "/pages/index/index" });
} else {
wx.showToast({ title: "登录失败", icon: "none" });
}
},
fail() {
wx.showToast({ title: "网络错误", icon: "none" });
}
});
} else {
// 用户拒绝授权
wx.showToast({ title: "请允许授权以完成登录", icon: "none" });
}
}
},
})

View File

@@ -0,0 +1,8 @@
<view class="avatar-box">
<t-avatar class="avatar-example" image="{{image}}" size="100px"/>
</view>
<view class="button">
<t-button theme="primary" size="large" block open-type="getPhoneNumber" getphonenumber="wxPhone">授权手机号登录</t-button>
<t-button size="large" block>手机号登录</t-button>
</view>

View File

@@ -0,0 +1,15 @@
.avatar-box{
width: 100vw;
height: 30vh;
display: flex;
justify-content: center;
align-items: center;
}
.button {
margin: 0 32rpx;
display: flex;
flex-direction: column; /* 垂直排列子元素 */
align-items: center; /* 水平居中子元素 */
gap: 2vh;
}

View File

@@ -0,0 +1,9 @@
{
"component": true,
"usingComponents": {
"t-grid": "tdesign-miniprogram/grid/grid",
"t-grid-item": "tdesign-miniprogram/grid-item/grid-item",
"t-avatar": "tdesign-miniprogram/avatar/avatar",
"t-avatar-group": "tdesign-miniprogram/avatar-group/avatar-group"
}
}

View File

@@ -0,0 +1,13 @@
Component({
data: {
img1: 'https://tdesign.gtimg.com/mobile/demos/example1.png',
img2: 'https://tdesign.gtimg.com/mobile/demos/example2.png',
img3: 'https://tdesign.gtimg.com/mobile/demos/example3.png',
image: 'https://tdesign.gtimg.com/mobile/demos/avatar1.png',
},
methods: {
userlogin(){
wx.navigateTo({url:'/pages/user-login/user-login'})
}
},
})

View File

@@ -0,0 +1,13 @@
<view class="user-contain">
<view class="user-avatar">
<t-avatar class="avatar-example" image="{{image}}" size="large" />
<a class="avatar-font" bind:tap="userlogin">点击登录/注册</a>
</view>
<view class="block" class="server1">
<t-grid column="{{4}}" theme="card" >
<t-grid-item t-class-image="image" text="标题文字" image="{{img1}}" />
<t-grid-item t-class-image="image" text="标题文字" image="{{img2}}" />
<t-grid-item t-class-image="image" text="标题文字" image="{{img3}}" />
</t-grid>
</view>
</view>

View File

@@ -0,0 +1,20 @@
.user-avatar{
margin-left: 40rpx;
width: 100vw;
display: flex;
align-items: center;
font-weight: bold;
}
.avatar-font{
margin-left: 30rpx;
}
.user-contain {
background-color: #f5f7fa; /* 浅灰色背景 */
height: 100vh;
}
.server1{
margin-top: 3vh;
}