地址路径修改

This commit is contained in:
2025-10-26 13:15:04 +08:00
parent be2323074b
commit 271b88232c
77 changed files with 13254 additions and 228 deletions

View File

@@ -0,0 +1,257 @@
// 头像组件逻辑
Component({
properties: {
// 头像URL
avatarUrl: {
type: String,
value: ''
},
// 头像尺寸rpx
size: {
type: Number,
value: 120
},
// 占位符文本
placeholderText: {
type: String,
value: '👤'
},
// 占位符文本大小
textSize: {
type: Number,
value: 40
},
// 是否可编辑
editable: {
type: Boolean,
value: false
},
// 头像形状circle圆形或 square方形
shape: {
type: String,
value: 'circle'
},
// 是否显示边框
bordered: {
type: Boolean,
value: false
},
// 是否显示阴影
shadow: {
type: Boolean,
value: false
}
},
data: {
showAvatarModal: false // 是否显示头像选择弹窗
},
methods: {
// 头像点击事件
onAvatarTap() {
if (this.properties.editable) {
this.showAvatarModal();
}
this.triggerEvent('tap', {
avatarUrl: this.properties.avatarUrl
});
},
// 显示头像选择弹窗
showAvatarModal() {
this.setData({
showAvatarModal: true
});
},
// 隐藏头像选择弹窗
hideAvatarModal() {
this.setData({
showAvatarModal: false
});
},
// 拍照
takePhoto() {
this.hideAvatarModal();
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['camera'],
camera: 'front',
success: (res) => {
if (res.tempFiles && res.tempFiles.length > 0) {
this.processImage(res.tempFiles[0].tempFilePath);
}
},
fail: (err) => {
console.error('拍照失败:', err);
wx.showToast({
title: '拍照失败',
icon: 'none'
});
}
});
},
// 从相册选择
chooseImage() {
this.hideAvatarModal();
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album'],
success: (res) => {
if (res.tempFiles && res.tempFiles.length > 0) {
this.processImage(res.tempFiles[0].tempFilePath);
}
},
fail: (err) => {
console.error('选择图片失败:', err);
wx.showToast({
title: '选择图片失败',
icon: 'none'
});
}
});
},
// 使用默认头像
useDefaultAvatar() {
this.hideAvatarModal();
// 触发默认头像选择事件
this.triggerEvent('change', {
avatarUrl: '',
isDefault: true
});
},
// 处理图片
processImage(tempFilePath) {
wx.showLoading({
title: '处理中...'
});
// 压缩图片
wx.compressImage({
src: tempFilePath,
quality: 80,
success: (res) => {
// 裁剪图片为正方形
this.cropImage(res.tempFilePath);
},
fail: (err) => {
console.error('图片压缩失败:', err);
wx.hideLoading();
wx.showToast({
title: '图片处理失败',
icon: 'none'
});
}
});
},
// 裁剪图片
cropImage(tempFilePath) {
// 获取图片信息
wx.getImageInfo({
src: tempFilePath,
success: (infoRes) => {
const { width, height } = infoRes;
const size = Math.min(width, height);
const x = (width - size) / 2;
const y = (height - size) / 2;
// 创建画布进行裁剪
const ctx = wx.createCanvasContext('avatar-canvas');
// 绘制圆形裁剪区域
ctx.save();
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI);
ctx.clip();
// 绘制图片
ctx.drawImage(tempFilePath, x, y, size, size, 0, 0, size, size);
ctx.restore();
// 将画布内容导出为图片
ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'avatar-canvas',
success: (canvasRes) => {
wx.hideLoading();
// 触发头像改变事件
this.triggerEvent('change', {
avatarUrl: canvasRes.tempFilePath,
isDefault: false
});
},
fail: (err) => {
console.error('画布导出失败:', err);
wx.hideLoading();
wx.showToast({
title: '头像处理失败',
icon: 'none'
});
}
});
});
},
fail: (err) => {
console.error('获取图片信息失败:', err);
wx.hideLoading();
wx.showToast({
title: '图片处理失败',
icon: 'none'
});
}
});
},
// 生成头像缩略图
generateThumbnail(avatarUrl, size = 60) {
return new Promise((resolve, reject) => {
if (!avatarUrl) {
resolve('');
return;
}
wx.getImageInfo({
src: avatarUrl,
success: (infoRes) => {
const ctx = wx.createCanvasContext('thumbnail-canvas');
// 绘制圆形缩略图
ctx.save();
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI);
ctx.clip();
ctx.drawImage(avatarUrl, 0, 0, size, size);
ctx.restore();
ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'thumbnail-canvas',
destWidth: size,
destHeight: size,
success: (res) => {
resolve(res.tempFilePath);
},
fail: (err) => {
reject(err);
}
});
});
},
fail: reject
});
});
}
}
});

View File

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

View File

@@ -0,0 +1,52 @@
<!-- 头像组件 -->
<view class="avatar-container">
<!-- 头像显示区域 -->
<view class="avatar-display" bindtap="onAvatarTap">
<view wx:if="{{avatarUrl}}" class="avatar-image-wrapper">
<image
class="avatar-image"
src="{{avatarUrl}}"
mode="aspectFill"
style="width: {{size}}rpx; height: {{size}}rpx;"
></image>
</view>
<view wx:else class="avatar-placeholder">
<text class="avatar-text" style="font-size: {{textSize}}rpx;">{{placeholderText}}</text>
</view>
<!-- 编辑图标 -->
<view wx:if="{{editable}}" class="avatar-edit-icon">
<text class="edit-icon">✏️</text>
</view>
</view>
<!-- 头像选择弹窗 -->
<view wx:if="{{showAvatarModal}}" class="avatar-modal">
<view class="modal-mask" bindtap="hideAvatarModal"></view>
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">选择头像</text>
<text class="modal-close" bindtap="hideAvatarModal">×</text>
</view>
<view class="avatar-options">
<!-- 拍照 -->
<view class="avatar-option" bindtap="takePhoto">
<text class="option-icon">📷</text>
<text class="option-text">拍照</text>
</view>
<!-- 从相册选择 -->
<view class="avatar-option" bindtap="chooseImage">
<text class="option-icon">🖼️</text>
<text class="option-text">从相册选择</text>
</view>
<!-- 默认头像 -->
<view class="avatar-option" bindtap="useDefaultAvatar">
<text class="option-icon">👤</text>
<text class="option-text">使用默认头像</text>
</view>
</view>
</view>
</view>
</view>

View File

@@ -0,0 +1,204 @@
/* 头像组件样式 */
.avatar-container {
position: relative;
display: inline-block;
}
/* 头像显示区域 */
.avatar-display {
position: relative;
border-radius: 50%;
overflow: hidden;
background-color: #f0f0f0;
border: 2px solid #e0e0e0;
cursor: pointer;
transition: all 0.3s ease;
}
.avatar-display:active {
transform: scale(0.95);
opacity: 0.8;
}
/* 头像图片容器 */
.avatar-image-wrapper {
width: 100%;
height: 100%;
border-radius: 50%;
overflow: hidden;
}
/* 头像图片 */
.avatar-image {
width: 100%;
height: 100%;
border-radius: 50%;
}
/* 头像占位符 */
.avatar-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 50%;
}
.avatar-text {
font-weight: bold;
text-transform: uppercase;
}
/* 编辑图标 */
.avatar-edit-icon {
position: absolute;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
border-radius: 50%;
width: 24rpx;
height: 24rpx;
display: flex;
align-items: center;
justify-content: center;
transform: translate(25%, 25%);
}
.edit-icon {
font-size: 12rpx;
color: white;
}
/* 头像选择弹窗 */
.avatar-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
}
.modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
}
.modal-content {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background: white;
border-radius: 20rpx 20rpx 0 0;
padding: 40rpx;
box-sizing: border-box;
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40rpx;
}
.modal-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.modal-close {
font-size: 40rpx;
color: #999;
padding: 10rpx;
}
/* 头像选项 */
.avatar-options {
display: flex;
flex-direction: column;
gap: 30rpx;
}
.avatar-option {
display: flex;
align-items: center;
padding: 30rpx;
background: #f8f9fa;
border-radius: 15rpx;
transition: all 0.3s ease;
}
.avatar-option:active {
background: #e9ecef;
transform: scale(0.98);
}
.option-icon {
font-size: 40rpx;
margin-right: 20rpx;
}
.option-text {
font-size: 28rpx;
color: #333;
}
/* 不同尺寸的头像样式 */
.avatar-small {
width: 80rpx;
height: 80rpx;
}
.avatar-medium {
width: 120rpx;
height: 120rpx;
}
.avatar-large {
width: 160rpx;
height: 160rpx;
}
.avatar-xlarge {
width: 200rpx;
height: 200rpx;
}
/* 圆形头像样式 */
.avatar-circle {
border-radius: 50%;
}
/* 方形头像样式 */
.avatar-square {
border-radius: 15rpx;
}
/* 带边框的头像 */
.avatar-bordered {
border: 3rpx solid #667eea;
}
/* 阴影效果 */
.avatar-shadow {
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
}