feat: 我的、设置、打印指南页面开发完成
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
"backgroundColor": "#F8F0E0",
|
||||
"usingComponents": {
|
||||
"van-icon": "@vant/weapp/icon/index",
|
||||
"nav-bar": "../../components3.0/nav-bar/nav-bar"
|
||||
"van-popup": "@vant/weapp/popup/index",
|
||||
"nav-bar": "../../components3.0/nav-bar/nav-bar",
|
||||
"toy-icon": "../../toy/icon/icon"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ page {
|
||||
}
|
||||
|
||||
.profile-hero__avatar {
|
||||
width: 256rpx;
|
||||
height: 256rpx;
|
||||
width: 224rpx;
|
||||
height: 224rpx;
|
||||
border-radius: 50%;
|
||||
border: 8rpx solid @bg-white;
|
||||
background: @bg-gray;
|
||||
@@ -98,7 +98,7 @@ page {
|
||||
|
||||
.profile-hero__name {
|
||||
margin-top: 32rpx;
|
||||
font-size: 40rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: @text-title;
|
||||
text-align: center;
|
||||
@@ -116,7 +116,7 @@ page {
|
||||
.profile-hero__stat {
|
||||
flex: 1;
|
||||
background: @bg-header;
|
||||
border-radius: @radius;
|
||||
border-radius: 48rpx;
|
||||
border: 1rpx solid rgba(124, 118, 106, 0.12);
|
||||
padding: 32rpx 24rpx;
|
||||
text-align: center;
|
||||
@@ -321,4 +321,144 @@ page {
|
||||
color: @text-secondary;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.profile-editor-popup {
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.profile-editor {
|
||||
overflow-y: auto;
|
||||
padding: 32rpx 40rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: @bg-white;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.profile-editor__header {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.profile-editor__title {
|
||||
display: block;
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: @text-title;
|
||||
}
|
||||
|
||||
.profile-editor__desc {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.5;
|
||||
color: @text-secondary;
|
||||
}
|
||||
|
||||
.profile-editor__avatar-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
|
||||
.profile-editor__avatar-button {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.profile-editor__avatar-button::after {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.profile-editor__avatar {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border-radius: 50%;
|
||||
background: @bg-gray;
|
||||
border: 2rpx dashed fade(@text-secondary, 30%);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.profile-editor__avatar-placeholder {
|
||||
width: 120rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.4;
|
||||
color: @text-secondary;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.profile-editor__avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.profile-editor__field {
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
|
||||
.profile-editor__label {
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: @text-title;
|
||||
}
|
||||
|
||||
.profile-editor__input {
|
||||
width: 100%;
|
||||
height: 96rpx;
|
||||
padding: 0 28rpx;
|
||||
border-radius: 24rpx;
|
||||
background: @bg-header;
|
||||
border: 1rpx solid rgba(124, 118, 106, 0.12);
|
||||
box-sizing: border-box;
|
||||
font-size: 30rpx;
|
||||
color: @text-title;
|
||||
}
|
||||
|
||||
.profile-editor__actions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 24rpx;
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
.profile-editor__action {
|
||||
height: 92rpx;
|
||||
border-radius: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.profile-editor__action--ghost {
|
||||
background: @bg-header;
|
||||
color: @text-title;
|
||||
border: 1rpx solid rgba(124, 118, 106, 0.12);
|
||||
}
|
||||
|
||||
.profile-editor__action--primary {
|
||||
background: @brand;
|
||||
color: @text-selected-btn;
|
||||
box-shadow: @shadow;
|
||||
}
|
||||
|
||||
.profile-editor__action--disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
@@ -1,31 +1,154 @@
|
||||
import { getTodayDownloadCount } from '../../utils/downloadPrint';
|
||||
import { getDownloadLogCount } from '../../utils/downloadLogs';
|
||||
import { getFavoriteCount } from '../../utils/favorites';
|
||||
import {
|
||||
getCachedUser,
|
||||
getUser,
|
||||
type UserInfo,
|
||||
updateUserProfile,
|
||||
} from '../../utils/auth';
|
||||
|
||||
Page({
|
||||
DEFAULT_AVATAR_URL: '/assets/imgs/doodle-head.png',
|
||||
data: {
|
||||
userName: '微信用户',
|
||||
avatarUrl: '',
|
||||
printCount: 0,
|
||||
favoriteCount: 0,
|
||||
version: '',
|
||||
isDevEnv: false,
|
||||
version: '3.0.0',
|
||||
showProfileEditor: false,
|
||||
draftNickName: '',
|
||||
draftAvatarUrl: '/assets/imgs/doodle-head.png',
|
||||
isSavingProfile: false,
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
const info = wx.getAccountInfoSync();
|
||||
const version = info.miniProgram.version || '开发版';
|
||||
const isDevEnv = info.miniProgram.envVersion === 'develop';
|
||||
this.setData({ version, isDevEnv });
|
||||
this.syncUserInfoFromApp();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.refreshStats();
|
||||
this.syncUserInfoFromApp();
|
||||
void this.refreshStats();
|
||||
},
|
||||
|
||||
refreshStats() {
|
||||
const printCount = getTodayDownloadCount();
|
||||
// 收藏数待与收藏页数据源打通后接入
|
||||
const favoriteCount = 0;
|
||||
this.setData({ printCount, favoriteCount });
|
||||
async syncUserInfoFromApp() {
|
||||
const app = getApp<IAppOption>();
|
||||
const cachedUser = app.globalData.user || getCachedUser();
|
||||
|
||||
if (cachedUser) {
|
||||
this.applyUserInfo(cachedUser);
|
||||
}
|
||||
|
||||
try {
|
||||
const latestUser = await getUser();
|
||||
this.applyUserInfo(latestUser);
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败', error);
|
||||
}
|
||||
},
|
||||
|
||||
applyUserInfo(user: UserInfo) {
|
||||
const userName = user.nickName?.trim() || '微信用户';
|
||||
const avatarUrl =
|
||||
user.avatarUrl || (this as any).DEFAULT_AVATAR_URL || '';
|
||||
this.setData({
|
||||
userName,
|
||||
avatarUrl,
|
||||
draftNickName: userName === '微信用户' ? '' : userName,
|
||||
draftAvatarUrl: avatarUrl,
|
||||
});
|
||||
},
|
||||
|
||||
async refreshStats() {
|
||||
try {
|
||||
const [printCount, favoriteCount] = await Promise.all([
|
||||
getDownloadLogCount(),
|
||||
getFavoriteCount(),
|
||||
]);
|
||||
this.setData({ printCount, favoriteCount });
|
||||
} catch (e) {
|
||||
console.error('refreshStats failed', e);
|
||||
}
|
||||
},
|
||||
|
||||
onOpenProfileEditor() {
|
||||
this.setData({
|
||||
showProfileEditor: true,
|
||||
draftNickName:
|
||||
this.data.userName === '微信用户' ? '' : this.data.userName,
|
||||
draftAvatarUrl: this.data.avatarUrl,
|
||||
});
|
||||
},
|
||||
|
||||
onCloseProfileEditor() {
|
||||
if (this.data.isSavingProfile) return;
|
||||
this.setData({ showProfileEditor: false });
|
||||
},
|
||||
|
||||
onChooseAvatar(e: WechatMiniprogram.CustomEvent<{ avatarUrl?: string }>) {
|
||||
const avatarUrl = e.detail?.avatarUrl || '';
|
||||
if (!avatarUrl) return;
|
||||
this.setData({ draftAvatarUrl: avatarUrl });
|
||||
},
|
||||
|
||||
onNicknameInput(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
|
||||
const nickName = (e.detail?.value || '').trim();
|
||||
this.setData({ draftNickName: nickName });
|
||||
},
|
||||
|
||||
async onSubmitProfile() {
|
||||
if (this.data.isSavingProfile) return;
|
||||
|
||||
const nickName = this.data.draftNickName.trim();
|
||||
if (!nickName) {
|
||||
wx.showToast({ title: '请输入昵称', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.data.draftAvatarUrl) {
|
||||
wx.showToast({ title: '请选择头像', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ isSavingProfile: true });
|
||||
|
||||
try {
|
||||
const avatarUrl = await this.persistAvatarIfNeeded(
|
||||
this.data.draftAvatarUrl,
|
||||
);
|
||||
const user = await updateUserProfile({
|
||||
nickName,
|
||||
avatarUrl,
|
||||
});
|
||||
|
||||
this.applyUserInfo(user);
|
||||
this.setData({ showProfileEditor: false });
|
||||
wx.showToast({ title: '资料已更新', icon: 'success' });
|
||||
} catch (error) {
|
||||
console.error('更新用户资料失败', error);
|
||||
wx.showToast({ title: '更新失败,请稍后重试', icon: 'none' });
|
||||
} finally {
|
||||
this.setData({ isSavingProfile: false });
|
||||
}
|
||||
},
|
||||
|
||||
async persistAvatarIfNeeded(avatarUrl: string): Promise<string> {
|
||||
if (!avatarUrl) return avatarUrl;
|
||||
if (
|
||||
avatarUrl.startsWith('cloud://') ||
|
||||
avatarUrl.startsWith('http://') ||
|
||||
avatarUrl.startsWith('https://')
|
||||
) {
|
||||
return avatarUrl;
|
||||
}
|
||||
|
||||
const user = await getUser();
|
||||
const cloudPath = `user-avatars/${user._id}-${Date.now()}.png`;
|
||||
const uploadRes = await wx.cloud.uploadFile({
|
||||
cloudPath,
|
||||
filePath: avatarUrl,
|
||||
});
|
||||
|
||||
return uploadRes.fileID;
|
||||
},
|
||||
|
||||
onGoToDownloads() {
|
||||
@@ -47,7 +170,7 @@ Page({
|
||||
},
|
||||
|
||||
onGoToSettings() {
|
||||
wx.showToast({ title: '功能开发中', icon: 'none' });
|
||||
wx.navigateTo({ url: '/supportPages/settings/settings' });
|
||||
},
|
||||
|
||||
onGoToDebug() {
|
||||
|
||||
@@ -8,19 +8,14 @@
|
||||
<view class="profile-hero__tint"></view>
|
||||
<view class="profile-hero__avatar-wrap">
|
||||
<view class="profile-hero__avatar">
|
||||
<text
|
||||
class="profile-hero__avatar-emoji"
|
||||
wx:if="{{!avatarUrl}}"
|
||||
>🦆</text
|
||||
>
|
||||
<image
|
||||
wx:else
|
||||
class="profile-hero__avatar-img"
|
||||
src="{{avatarUrl}}"
|
||||
mode="aspectFill" />
|
||||
</view>
|
||||
<view
|
||||
class="profile-hero__edit-badge"
|
||||
bindtap="onOpenProfileEditor"
|
||||
aria-role="button"
|
||||
aria-label="编辑头像">
|
||||
<van-icon name="edit" size="28rpx" color="#6c5a00" />
|
||||
@@ -73,9 +68,13 @@
|
||||
</view>
|
||||
<text class="profile-row__label">打印指南</text>
|
||||
</view>
|
||||
<text class="profile-row__chevron">›</text>
|
||||
<toy-icon
|
||||
class="profile-row__chevron"
|
||||
name="arrow-right"
|
||||
size="40rpx"
|
||||
color="#9a958b" />
|
||||
</view>
|
||||
<view class="profile-row" bindtap="onGoToFeedback">
|
||||
<!-- <view class="profile-row" bindtap="onGoToFeedback">
|
||||
<view class="profile-row__left">
|
||||
<view class="profile-row__icon-bg">
|
||||
<van-icon
|
||||
@@ -85,8 +84,12 @@
|
||||
</view>
|
||||
<text class="profile-row__label">提交反馈</text>
|
||||
</view>
|
||||
<text class="profile-row__chevron">›</text>
|
||||
</view>
|
||||
<toy-icon
|
||||
class="profile-row__chevron"
|
||||
name="arrow-right"
|
||||
size="40rpx"
|
||||
color="#9a958b" />
|
||||
</view> -->
|
||||
<view class="profile-row" bindtap="onGoToSettings">
|
||||
<view class="profile-row__left">
|
||||
<view class="profile-row__icon-bg">
|
||||
@@ -97,7 +100,11 @@
|
||||
</view>
|
||||
<text class="profile-row__label">设置</text>
|
||||
</view>
|
||||
<text class="profile-row__chevron">›</text>
|
||||
<toy-icon
|
||||
class="profile-row__chevron"
|
||||
name="arrow-right"
|
||||
size="40rpx"
|
||||
color="#9a958b" />
|
||||
</view>
|
||||
<view
|
||||
wx:if="{{isDevEnv}}"
|
||||
@@ -109,9 +116,13 @@
|
||||
</view>
|
||||
<text class="profile-row__label">Debug 工具</text>
|
||||
</view>
|
||||
<text class="profile-row__chevron">›</text>
|
||||
<toy-icon
|
||||
class="profile-row__chevron"
|
||||
name="arrow-right"
|
||||
size="40rpx"
|
||||
color="#9a958b" />
|
||||
</view>
|
||||
<view
|
||||
<!-- <view
|
||||
class="profile-row profile-row--last"
|
||||
bindtap="onGoToAbout">
|
||||
<view class="profile-row__left">
|
||||
@@ -123,12 +134,16 @@
|
||||
</view>
|
||||
<text class="profile-row__label">关于涂鸦丫</text>
|
||||
</view>
|
||||
<text class="profile-row__chevron">›</text>
|
||||
</view>
|
||||
<toy-icon
|
||||
class="profile-row__chevron"
|
||||
name="arrow-right"
|
||||
size="40rpx"
|
||||
color="#9a958b" />
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<!-- 专业版推广(Stitch 深色卡) -->
|
||||
<view class="profile-upsell" bindtap="onGoToPremium">
|
||||
<!-- <view class="profile-upsell" bindtap="onGoToPremium">
|
||||
<van-icon
|
||||
name="gem-o"
|
||||
class="profile-upsell__deco"
|
||||
@@ -141,13 +156,73 @@
|
||||
>
|
||||
<view class="profile-upsell__btn">立即升级</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<view class="profile-version">
|
||||
<text class="profile-version__text"
|
||||
>Doodle Mini v{{version}}</text
|
||||
>
|
||||
<text class="profile-version__text">涂鸦丫 v{{version}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<van-popup
|
||||
show="{{showProfileEditor}}"
|
||||
position="bottom"
|
||||
round
|
||||
safe-area-inset-bottom="{{false}}"
|
||||
custom-class="profile-editor-popup"
|
||||
bind:close="onCloseProfileEditor">
|
||||
<view class="profile-editor">
|
||||
<view class="profile-editor__header">
|
||||
<text class="profile-editor__title">完善资料</text>
|
||||
<text class="profile-editor__desc"
|
||||
>选择头像并填写昵称后保存</text
|
||||
>
|
||||
</view>
|
||||
|
||||
<view class="profile-editor__avatar-section">
|
||||
<button
|
||||
class="profile-editor__avatar-button"
|
||||
open-type="chooseAvatar"
|
||||
bindchooseavatar="onChooseAvatar">
|
||||
<view class="profile-editor__avatar">
|
||||
<text
|
||||
class="profile-editor__avatar-placeholder"
|
||||
wx:if="{{!draftAvatarUrl}}"
|
||||
>选择头像</text
|
||||
>
|
||||
<image
|
||||
wx:else
|
||||
class="profile-editor__avatar-img"
|
||||
src="{{draftAvatarUrl}}"
|
||||
mode="aspectFill" />
|
||||
</view>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<view class="profile-editor__field">
|
||||
<text class="profile-editor__label">昵称</text>
|
||||
<input
|
||||
class="profile-editor__input"
|
||||
type="nickname"
|
||||
placeholder="请输入昵称"
|
||||
maxlength="20"
|
||||
value="{{draftNickName}}"
|
||||
bindblur="onNicknameInput"
|
||||
bindinput="onNicknameInput" />
|
||||
</view>
|
||||
|
||||
<view class="profile-editor__actions">
|
||||
<view
|
||||
class="profile-editor__action profile-editor__action--ghost"
|
||||
bindtap="onCloseProfileEditor">
|
||||
取消
|
||||
</view>
|
||||
<view
|
||||
class="profile-editor__action profile-editor__action--primary {{isSavingProfile ? 'profile-editor__action--disabled' : ''}}"
|
||||
bindtap="onSubmitProfile">
|
||||
{{isSavingProfile ? '保存中...' : '保存'}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</van-popup>
|
||||
</view>
|
||||
|
||||
Reference in New Issue
Block a user