upload project

This commit is contained in:
unknown 2025-12-27 17:16:03 +08:00
commit 06961cae04
422 changed files with 110626 additions and 0 deletions

352
custom-tab-bar/index.js Normal file
View file

@ -0,0 +1,352 @@
const config = require('../config/config.js');
const apiClient = require('../utils/api-client.js');
Component({
data: {
selected: 0,
color: '#999999',
selectedColor: '#ffffff',
showCameraAction: false, // 拍照弹窗显示状态
cameraActive: false, // 发布按钮激活状态
list: [
{
pagePath: '/pages/map/map',
text: '发现',
iconPath: '/images/index/location.png',
selectedIconPath: '/images/index/location-active.png'
},
{
pagePath: '/pages/circle/circle',
text: '圈子',
iconPath: '/images/index/circle.png',
selectedIconPath: '/images/index/circle-active.png'
},
{
pagePath: '/subpackages/media/camera/camera',
iconPath: '/images/index/phone.png',
text: '发布',
selectedIconPath: '/images/index/phone-active.png'
},
{
pagePath: '/pages/message/message',
text: '聊天',
iconPath: '/images/index/message.png',
selectedIconPath: '/images/index/message-active.png'
},
{
pagePath: '/pages/social/friends/friends',
text: '好友',
iconPath: '/images/index/friend.png',
selectedIconPath: '/images/index/friend-active.png'
}
]
},
/**
* 用户点击右上角分享
*/
onShareAppMessage(options) {
// options.from 可以是 'button' 或 'menu'
// 'button' 表示通过页面内的分享按钮触发
// 'menu' 表示通过右上角菜单的分享按钮触发
return {
title: 'Find Me', // 分享标题
path: '/custom-tab-bar/index/index', // 分享路径,必须是以 / 开头的完整路径
imageUrl: '/images/findme-logo.png', // 分享图标,可以是本地图片或网络图片
success(res) {
// 分享成功后的回调
console.log('分享成功', res);
// 可以在这里添加统计代码等
},
fail(res) {
// 分享失败后的回调
console.log('分享失败', res);
}
}
},
attached() {
// 已通过CSS调整适配所有设备
try {
const counts = wx.getStorageSync('unreadCounts') || {};
const friends = Number(counts.friends || 0);
const messages = Number(counts.messages || 0);
if (friends || messages) {
this.setData({
friendsBadge: friends,
messagesBadge: messages
});
}
} catch (_) {}
},
methods: {
// 对外暴露:设置好友请求角标数量
setFriendsBadge(count) {
const n = Number(count) || 0;
if (this.data.friendsBadge === n) return;
this.setData({ friendsBadge: n < 0 ? 0 : n });
},
// 对外暴露:设置消息未读角标数量
setMessagesBadge(count) {
const n = Number(count) || 0;
if (this.data.messagesBadge === n) return;
this.setData({ messagesBadge: n < 0 ? 0 : n });
},
// 清除所有角标
clearBadges() {
this.setData({ friendsBadge: 0, messagesBadge: 0 });
},
switchTab(e) {
const data = e.currentTarget.dataset;
const url = data.path;
const index = data.index;
// 获取当前页面信息
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
// 检查是否是"发布"按钮索引2- 直接跳转到编辑页面
if (index === 2) {
// 切换发布按钮激活状态
this.setData({ cameraActive: !this.data.cameraActive });
// 检查登录状态
const app = getApp();
if (!app.globalData.isLoggedIn) {
wx.navigateTo({
url: '/pages/login/login?from=camera'
});
return;
}
// 已登录时直接跳转到编辑页面
wx.navigateTo({
url: '/subpackages/media/edits/edits',
fail: (err) => {
console.error('跳转编辑页面失败:', err);
wx.showToast({
title: '跳转失败,请重试',
icon: 'none'
});
// 跳转失败时重置激活状态
this.setData({ cameraActive: false });
}
});
return;
}
// 切换到其他按钮时,取消发布按钮激活状态
if (this.data.cameraActive) {
this.setData({ cameraActive: false });
}
// 先更新选中状态(其他 tabBar 页面)
this.setData({
selected: index
});
// 检查是否是"发现"按钮索引0
if (index === 0) {
// 检查当前是否已经在地图页面
if (currentPage.route === 'pages/map/map') {
// 如果已经在地图页面,直接打开地点收藏栏
currentPage.onOpenLocationFavoriteBar();
} else {
const app = getApp();
// 如果不在地图页面,先跳转到地图页面,然后通过全局变量标记需要打开收藏栏
wx.switchTab({
url,
success: () => {
// 设置全局变量,让地图页面加载后知道需要打开收藏栏
app.globalData.needOpenLocationFavoriteBar = true;
}
});
}
return;
}
// 检查是否是"圈子"按钮索引1
if (index === 1) {
// 检查登录状态
const app = getApp();
if (!app.globalData.isLoggedIn) {
wx.navigateTo({
url: '/pages/login/login?from=circle'
});
return;
}
// 正常跳转到圈子页面
wx.switchTab({
url
});
return;
}
// 检查是否是"聊天"按钮索引3
if (index === 3) {
// 检查登录状态
const app = getApp();
if (!app.globalData.isLoggedIn) {
wx.navigateTo({
url: '/pages/login/login?from=message'
});
return;
}
// 已登录时正常跳转
wx.switchTab({
url
});
return;
}
// 检查是否是"我的"按钮索引4- 跳转到好友列表页面
if (index === 4) {
// 检查登录状态
const app = getApp();
if (!app.globalData.isLoggedIn) {
wx.navigateTo({
url: '/pages/login/login?from=friends'
});
return;
}
// 已登录时跳转到好友列表页面(使用 switchTab因为它在 tabBar 中)
wx.switchTab({
url: '/pages/social/friends/friends'
});
return;
}
// 其他按钮正常跳转
wx.switchTab({
url
});
},
// 显示拍照弹窗
showCameraActionSheet() {
this.setData({ showCameraAction: true });
},
// 隐藏拍照弹窗
hideCameraActionSheet() {
this.setData({ showCameraAction: false, cameraActive: false });
},
// 拍照
takePhoto() {
this.hideCameraActionSheet();
wx.navigateTo({
url: '/subpackages/media/camera/camera',
fail: (err) => {
console.error('跳转拍照页面失败:', err);
wx.showToast({
title: '跳转失败,请重试',
icon: 'none'
});
}
});
},
// 从相册选择
chooseImage() {
this.hideCameraActionSheet();
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album'],
success: (res) => {
const tempFilePath = res.tempFilePaths[0];
wx.showLoading({ title: '上传中...', mask: true });
// 上传图片
this.uploadImage(tempFilePath)
.then(imageUrl => {
wx.hideLoading();
if (imageUrl) {
wx.navigateTo({
url: `/subpackages/media/edits/edits?imagePath=${encodeURIComponent(imageUrl)}`,
fail: (err) => {
console.error('跳转编辑页失败:', err);
wx.showToast({
title: '跳转失败,请重试',
icon: 'none'
});
}
});
}
})
.catch(error => {
wx.hideLoading();
console.error('上传失败:', error);
wx.showToast({
title: error.message || '上传失败,请重试',
icon: 'none'
});
});
},
fail: (error) => {
console.error('选择图片失败:', error);
if (error.errMsg && !error.errMsg.includes('cancel')) {
wx.showToast({
title: '选择图片失败',
icon: 'none'
});
}
}
});
},
// 上传图片
uploadImage(tempFilePath) {
return new Promise((resolve, reject) => {
wx.uploadFile({
url: `${config.api.baseUrl}/api/v1/file/upload`,
filePath: tempFilePath,
name: 'file',
formData: {
file_type: 'image',
usage_type: 'feed'
},
header: {
'Authorization': `Bearer ${apiClient.getToken()}`
},
success: (uploadRes) => {
if (apiClient.is401Error(uploadRes)) {
const app = getApp();
const isLoggedIn = app?.globalData?.isLoggedIn || false;
apiClient.handle401Error(isLoggedIn);
if (isLoggedIn) {
reject(new Error('登录已过期,请重新登录'));
} else {
resolve(null);
}
return;
}
try {
const data = JSON.parse(uploadRes.data);
if (data.code === 0) {
const fileData = data?.data?.data || data?.data || {};
const imageUrl = fileData.file_url || fileData.fileUrl || fileData.url;
if (imageUrl) {
resolve(imageUrl);
} else {
reject(new Error('上传成功但未获取到图片URL'));
}
} else {
reject(new Error(data.message || '上传失败'));
}
} catch (error) {
reject(new Error('响应解析失败'));
}
},
fail: (error) => {
console.error('上传失败:', error);
reject(new Error(error.errMsg || '上传失败'));
}
});
});
}
}
});

View file

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

33
custom-tab-bar/index.wxml Normal file
View file

@ -0,0 +1,33 @@
<!--custom-tab-bar/index.wxml-->
<view class="tab-bar-glass tab-bar">
<view wx:for="{{list}}" wx:key="index"
class="tab-bar-item {{selected === index ? 'tab-active' : ''}} {{index === 2 ? 'camera-tab-item' : ''}}"
data-path="{{item.pagePath}}"
data-index="{{index}}"
bindtap="switchTab">
<!-- 拍照按钮索引2根据激活状态显示图标其他按钮根据选中状态显示 -->
<image class="tab-bar-icon {{selected === index ? 'tab-icon-active' : ''}} {{index === 2 && cameraActive ? 'tab-icon-active camera-icon-large' : ''}} {{index === 2 && !cameraActive ? 'camera-icon-normal' : ''}}"
src="{{index === 2 ? (cameraActive ? item.selectedIconPath : item.iconPath) : (selected === index ? item.selectedIconPath : item.iconPath)}}"
mode="aspectFit" />
<!-- 所有按钮未选中/未激活时显示文字 -->
<text wx:if="{{index === 2 ? !cameraActive : selected !== index}}" class="tab-bar-text" style="color: {{selected === index ? selectedColor : color}};">{{item.text}}</text>
</view>
</view>
<!-- 拍照功能弹窗 -->
<view class="camera-action-sheet {{showCameraAction ? 'show' : ''}}">
<view class="action-sheet-mask" bindtap="hideCameraActionSheet"></view>
<view class="action-sheet-content">
<view class="action-sheet-item primary" bindtap="takePhoto">
<text class="action-text">拍照</text>
</view>
<view class="action-sheet-divider-thin"></view>
<view class="action-sheet-item primary" bindtap="chooseImage">
<text class="action-text">从相册选择</text>
</view>
<view class="action-sheet-divider"></view>
<view class="action-sheet-item cancel" bindtap="hideCameraActionSheet">
<text class="action-text">取消</text>
</view>
</view>
</view>

163
custom-tab-bar/index.wxss Normal file
View file

@ -0,0 +1,163 @@
/* custom-tab-bar/index.wxss - 自定义底部导航栏样式文件 */
.tab-bar {
position: fixed; /* 固定定位,使导航栏始终显示在屏幕底部 */
bottom: 40rpx; /* 距离屏幕底部20px -> 40rpx */
left: 100rpx; /* 距离屏幕左侧50px -> 100rpx */
right: 100rpx; /* 距离屏幕右侧50px -> 100rpx */
min-height: 200rpx; /* 导航栏最小高度(用户希望保持较大值) */
height: auto; /* 高度自适应内容 */
display: flex; /* 使用flex布局 */
justify-content: space-around; /* 水平均匀分布子元素 */
align-items: center; /* 垂直居中对齐子元素 */
padding: 20rpx; /* 内边距10px -> 20rpx */
box-sizing: border-box; /* 盒模型为border-box宽高包含内边距和边框 */
z-index: 9999; /* 层级设为最高,确保在其他元素之上 */
border-radius: 52rpx; /* 设置圆角,创建胶囊形状 26px -> 52rpx */
}
/* 深灰色玻璃效果 - 继承自app.wxss并增强 */
.tab-bar-glass {
/* 基础玻璃效果 */
background: rgba(30, 30, 30, 0.7); /* 设置半透明深灰色背景透明度0.7 */
backdrop-filter: blur(20rpx); /* 设置背景模糊效果10px -> 20rpx */
-webkit-backdrop-filter: blur(20rpx); /* WebKit内核浏览器兼容设置背景模糊效果 */
/* 添加细微边框增强效果 */
border-top: 2rpx solid rgba(255, 255, 255, 0.1); /* 顶部边框为1px -> 2rpx白色半透明线 */
/* 阴影效果增强层次感 */
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.1); /* 设置底部阴影,增强悬浮感 2px -> 4rpx, 10px -> 20rpx */
}
.tab-bar-item {
flex: 1; /* 让每个按钮占据相同的宽度 */
display: flex; /* 使用flex布局 */
flex-direction: column; /* 垂直方向排列子元素(图标在上,文字在下) */
align-items: center; /* 水平居中对齐子元素 */
justify-content: center; /* 垂直居中对齐子元素 */
height: 100%; /* 高度充满父容器 */
box-sizing: border-box; /* 盒模型为border-box */
}
.tab-bar-icon {
width: 55rpx; /* 图标宽度 */
height: 55rpx; /* 图标高度 */
margin-bottom: 8rpx; /* 与下方文字的间距 */
display: block; /* 显示为块级元素 */
transition: transform 0.3s ease, width 0.3s ease, height 0.3s ease; /* 添加过渡效果 */
}
/* 🔥 所有tab选中时图标放大 */
.tab-bar-icon.tab-icon-active {
width: 80rpx; /* 选中时图标宽度增大 */
height: 80rpx; /* 选中时图标高度增大 */
margin-bottom: 0; /* 选中时没有文字,不需要间距 */
}
/* 拍照按钮索引2未激活时正常大小图标显示文字 */
.camera-icon-normal {
width: 55rpx !important; /* 正常大小 */
height: 55rpx !important; /* 正常大小 */
margin-bottom: 8rpx !important; /* 有文字,需要间距 */
}
/* 拍照按钮索引2激活时大图标不显示文字 */
.camera-icon-large {
width: 80rpx !important; /* 拍照按钮图标更大 */
height: 80rpx !important; /* 拍照按钮图标更大 */
margin-bottom: 0 !important; /* 没有文字,不需要间距 */
}
.tab-bar-text {
font-size: 24rpx; /* 文字大小12px -> 24rpx */
line-height: 24rpx; /* 行高12px -> 24rpx与字体大小一致确保单行显示 */
}
/* 触摸反馈效果 */
.tab-bar-item:active {
opacity: 0.7; /* 触摸时透明度降低到0.7,提供视觉反馈 */
}
/* 拍照功能弹窗样式 */
.camera-action-sheet {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10000;
transform: none !important;
-webkit-transform: none !important;
}
.camera-action-sheet.show {
display: block;
}
.action-sheet-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
background-color: rgba(0, 0, 0, 0.4);
}
.action-sheet-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
background: #222;
border-radius: 16px 16px 0 0;
padding: 8px 0;
}
.action-sheet-item {
padding: 20px 0;
text-align: center;
background: #222;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
position: relative;
}
.action-sheet-item::after {
display: none;
}
.action-sheet-item.primary {
background: #222;
}
.action-sheet-item.cancel {
background: #222;
margin-top: 8px;
}
.action-sheet-item.cancel::after {
display: none;
}
.action-sheet-divider {
height: 8px;
background-color: #111;
margin: 8px 0;
}
.action-sheet-divider-thin {
height: 2px;
background-color: #111;
margin: 4px 0;
}
.action-text {
font-size: 16px;
color: #fff;
}