|
|
@@ -59,6 +59,21 @@ interface WechatUserInfoApiResponse {
|
|
|
data: GeneratedTypeLiteralInterface_1;
|
|
|
}
|
|
|
|
|
|
+interface VipFeature {
|
|
|
+ icon: Resource;
|
|
|
+ title: string;
|
|
|
+ description: string;
|
|
|
+ isVipOnly: boolean;
|
|
|
+}
|
|
|
+
|
|
|
+interface VipPlan {
|
|
|
+ name: string;
|
|
|
+ price: string;
|
|
|
+ originalPrice: string;
|
|
|
+ duration: string;
|
|
|
+ features: string[];
|
|
|
+}
|
|
|
+
|
|
|
@Component
|
|
|
@Entry
|
|
|
export struct UserCenter {
|
|
|
@@ -86,6 +101,16 @@ export struct UserCenter {
|
|
|
.setOnLeftClickListener(() => {
|
|
|
router.back();
|
|
|
});
|
|
|
+ @State vipFeatures: VipFeature[] = [
|
|
|
+ { icon: $r('app.media.small_music'), title: '无损音质', description: '支持FLAC、WAV等无损格式', isVipOnly: true },
|
|
|
+ { icon: $r('app.media.small_music'), title: '歌词显示', description: '支持LRC歌词同步显示', isVipOnly: false },
|
|
|
+ { icon: $r('app.media.small_music'), title: '智能歌单', description: 'AI智能推荐歌单', isVipOnly: true },
|
|
|
+ { icon: $r('app.media.small_music'), title: '主题定制', description: '自定义播放器主题', isVipOnly: true }
|
|
|
+ ];
|
|
|
+ @State vipPlans: VipPlan[] = [
|
|
|
+ { name: '月度会员', price: '¥18', originalPrice: '¥30', duration: '30天', features: ['无损音质', '智能歌单', '主题定制'] },
|
|
|
+ { name: '年度会员', price: '¥128', originalPrice: '¥360', duration: '365天', features: ['无损音质', '智能歌单', '主题定制', '专属客服'] }
|
|
|
+ ];
|
|
|
|
|
|
// 微信回调处理
|
|
|
private onWXResp: OnWXResp = (resp) => {
|
|
|
@@ -179,150 +204,260 @@ export struct UserCenter {
|
|
|
|
|
|
build() {
|
|
|
Column() {
|
|
|
- // 顶部安全区和标题栏
|
|
|
Column() {
|
|
|
Line().width('100%').height('100%')
|
|
|
}
|
|
|
- .height(this.isPhoneLan()?0:px2vp(AppUtil.getStatusBarHeight()))
|
|
|
+ .height(this.isPhoneLan() ? 0 : px2vp(AppUtil.getStatusBarHeight()))
|
|
|
.backgroundColor($r('app.color.title_bar_bg'))
|
|
|
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
|
|
|
TitleBar({ model: this.titleBarModel })
|
|
|
|
|
|
- // 用户信息卡片
|
|
|
- Column() {
|
|
|
- // 头像居中
|
|
|
- Row() {
|
|
|
- Blank().layoutWeight(1)
|
|
|
- Image(this.userAvatarUrl && this.userAvatarUrl.length > 0 ? this.userAvatarUrl : this.userAvatar)
|
|
|
- .width(80)
|
|
|
- .height(80)
|
|
|
- .borderRadius('50%')
|
|
|
- .clip(true)
|
|
|
- .backgroundColor(Color.White)
|
|
|
- .shadow({ radius: 8, color: 0x11000000, offsetX: 0, offsetY: 2 })
|
|
|
- Blank().layoutWeight(1)
|
|
|
+ Scroll() {
|
|
|
+ Column() {
|
|
|
+ this.buildUserInfoCard()
|
|
|
+ this.buildVipFeatures()
|
|
|
+ this.buildVipPlans()
|
|
|
+ this.buildFunctionMenu()
|
|
|
+ this.buildLoginButton()
|
|
|
}
|
|
|
- .margin({ top: 32, bottom: 12 })
|
|
|
-
|
|
|
- // 昵称
|
|
|
- Text(this.isLogin ? this.userName : '未登录用户')
|
|
|
- .fontSize(22)
|
|
|
- .fontWeight(FontWeight.Bold)
|
|
|
- .fontColor(Color.Black)
|
|
|
- .margin({ bottom: 4 })
|
|
|
- .alignSelf(ItemAlign.Center)
|
|
|
+ .width('100%')
|
|
|
+ }
|
|
|
+ .scrollBar(BarState.Off)
|
|
|
+ .edgeEffect(EdgeEffect.Spring)
|
|
|
+ }
|
|
|
+ .backgroundColor(0xFFF6F7FA)
|
|
|
+ .width('100%')
|
|
|
+ .height('100%')
|
|
|
+ }
|
|
|
|
|
|
- // 身份信息
|
|
|
- if (this.isLogin) {
|
|
|
- if (this.hasActiveSubscription) {
|
|
|
- Text(this.subscriptionName)
|
|
|
- .fontSize(16)
|
|
|
- .fontColor(Color.Red)
|
|
|
- .alignSelf(ItemAlign.Center)
|
|
|
- Text('到期:' + this.subscriptionEndDate)
|
|
|
- .fontSize(14)
|
|
|
- .fontColor(Color.Gray)
|
|
|
- .alignSelf(ItemAlign.Center)
|
|
|
- } else {
|
|
|
- Text('普通用户')
|
|
|
- .fontSize(15)
|
|
|
- .fontColor(Color.Grey)
|
|
|
- .alignSelf(ItemAlign.Center)
|
|
|
+ // 用户信息卡片
|
|
|
+ @Builder
|
|
|
+ buildUserInfoCard() {
|
|
|
+ Column() {
|
|
|
+ Row() {
|
|
|
+ Image(this.userAvatarUrl && this.userAvatarUrl.length > 0 ? this.userAvatarUrl : this.userAvatar)
|
|
|
+ .width(80)
|
|
|
+ .height(80)
|
|
|
+ .borderRadius('50%')
|
|
|
+ .clip(true)
|
|
|
+ .backgroundColor(Color.White)
|
|
|
+ .shadow({ radius: 8, color: 0x11000000, offsetX: 0, offsetY: 2 })
|
|
|
+ Column() {
|
|
|
+ Text(this.isLogin ? this.userName : '未登录用户')
|
|
|
+ .fontSize(22)
|
|
|
+ .fontWeight(FontWeight.Bold)
|
|
|
+ .fontColor(Color.Black)
|
|
|
+ if (this.isLogin) {
|
|
|
+ if (this.hasActiveSubscription) {
|
|
|
+ Text(this.subscriptionName)
|
|
|
+ .fontSize(16)
|
|
|
+ .fontColor(Color.Red)
|
|
|
+ Text('到期:' + this.subscriptionEndDate)
|
|
|
+ .fontSize(14)
|
|
|
+ .fontColor(Color.Gray)
|
|
|
+ } else {
|
|
|
+ Text('普通用户')
|
|
|
+ .fontSize(15)
|
|
|
+ .fontColor(Color.Grey)
|
|
|
+ }
|
|
|
}
|
|
|
- } else {
|
|
|
- Text('请先登录')
|
|
|
- .fontSize(15)
|
|
|
- .fontColor(Color.Grey)
|
|
|
- .alignSelf(ItemAlign.Center)
|
|
|
}
|
|
|
+ .alignItems(HorizontalAlign.Start)
|
|
|
+ .margin({ left: 16 })
|
|
|
}
|
|
|
- .backgroundColor(Color.White)
|
|
|
- .borderRadius(24)
|
|
|
- .margin({ left: 20, right: 20, top: 20, bottom: 0 })
|
|
|
- .shadow({ radius: 12, color: 0x11000000, offsetX: 0, offsetY: 2 })
|
|
|
+ .width('100%')
|
|
|
+ .padding(16)
|
|
|
+ }
|
|
|
+ .backgroundColor(Color.White)
|
|
|
+ .borderRadius(24)
|
|
|
+ .margin({ left: 20, right: 20, top: 20 })
|
|
|
+ .shadow({ radius: 12, color: 0x11000000, offsetX: 0, offsetY: 2 })
|
|
|
+ }
|
|
|
|
|
|
- // 操作列表
|
|
|
- Column() {
|
|
|
- this.menuItem($r('app.media.icon_favorite'), '我的收藏', () => {
|
|
|
- if (!this.isLogin) {
|
|
|
- ToastUtil.showToast('请先登录')
|
|
|
- return
|
|
|
- }
|
|
|
- ToastUtil.showToast('我的收藏')
|
|
|
- })
|
|
|
- Line().width('90%').height(0.5).backgroundColor(0xFFEFEFEF).alignSelf(ItemAlign.Center)
|
|
|
- this.menuItem($r('app.media.icon_history'), '历史记录', () => {
|
|
|
- if (!this.isLogin) {
|
|
|
- ToastUtil.showToast('请先登录')
|
|
|
- return
|
|
|
+ // 会员权益展示
|
|
|
+ @Builder
|
|
|
+ buildVipFeatures() {
|
|
|
+ Column() {
|
|
|
+ Text('会员权益')
|
|
|
+ .fontSize(18)
|
|
|
+ .fontWeight(FontWeight.Bold)
|
|
|
+ .margin({ top: 24, bottom: 16 })
|
|
|
+ Grid() {
|
|
|
+ ForEach(this.vipFeatures, (feature: VipFeature) => {
|
|
|
+ GridItem() {
|
|
|
+ Column() {
|
|
|
+ Image(feature.icon)
|
|
|
+ .width(32)
|
|
|
+ .height(32)
|
|
|
+ .margin({ bottom: 8 })
|
|
|
+ Text(feature.title)
|
|
|
+ .fontSize(16)
|
|
|
+ .fontWeight(FontWeight.Medium)
|
|
|
+ Text(feature.description)
|
|
|
+ .fontSize(12)
|
|
|
+ .fontColor(Color.Gray)
|
|
|
+ .margin({ top: 4 })
|
|
|
+ if (feature.isVipOnly) {
|
|
|
+ Text('VIP专享')
|
|
|
+ .fontSize(10)
|
|
|
+ .fontColor(Color.Red)
|
|
|
+ .backgroundColor('#FFF0F0')
|
|
|
+ .borderRadius(8)
|
|
|
+ .padding({ left: 6, right: 6, top: 2, bottom: 2 })
|
|
|
+ .margin({ top: 4 })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .height(120)
|
|
|
+ .backgroundColor(Color.White)
|
|
|
+ .borderRadius(12)
|
|
|
+ .padding(12)
|
|
|
}
|
|
|
- ToastUtil.showToast('历史记录')
|
|
|
- })
|
|
|
- Line().width('90%').height(0.5).backgroundColor(0xFFEFEFEF).alignSelf(ItemAlign.Center)
|
|
|
- this.menuItem($r('app.media.icon_person2'), '联系客服', () => {
|
|
|
- Utility.copyText(CommonConstants.CONTACT_MAIL)
|
|
|
- ToastUtil.showToast('已复制客服邮箱')
|
|
|
})
|
|
|
}
|
|
|
- .backgroundColor(Color.White)
|
|
|
- .borderRadius(24)
|
|
|
- .margin({ left: 20, right: 20, top: 24, bottom: 0 })
|
|
|
- .shadow({ radius: 8, color: 0x11000000, offsetX: 0, offsetY: 2 })
|
|
|
+ .columnsTemplate('1fr 1fr')
|
|
|
+ .columnsGap(12)
|
|
|
+ .rowsGap(12)
|
|
|
+ .margin({ left: 20, right: 20 })
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 退出登录/登录按钮
|
|
|
- Row() {
|
|
|
- Blank().layoutWeight(1)
|
|
|
- if (this.isLogin) {
|
|
|
- Button('退出登录')
|
|
|
+ // 会员套餐选择
|
|
|
+ @Builder
|
|
|
+ buildVipPlans() {
|
|
|
+ Column() {
|
|
|
+ Text('会员套餐')
|
|
|
+ .fontSize(18)
|
|
|
+ .fontWeight(FontWeight.Bold)
|
|
|
+ .margin({ top: 24, bottom: 16 })
|
|
|
+ ForEach(this.vipPlans, (plan: VipPlan) => {
|
|
|
+ Row() {
|
|
|
+ Column() {
|
|
|
+ Text(plan.name)
|
|
|
+ .fontSize(16)
|
|
|
+ .fontWeight(FontWeight.Bold)
|
|
|
+ Text(plan.duration)
|
|
|
+ .fontSize(12)
|
|
|
+ .fontColor(Color.Gray)
|
|
|
+ .margin({ top: 4 })
|
|
|
+ }
|
|
|
+ .layoutWeight(1)
|
|
|
+ Column() {
|
|
|
+ Text(plan.price)
|
|
|
+ .fontSize(20)
|
|
|
+ .fontWeight(FontWeight.Bold)
|
|
|
+ .fontColor(Color.Red)
|
|
|
+ Text(plan.originalPrice)
|
|
|
+ .fontSize(12)
|
|
|
+ .fontColor(Color.Gray)
|
|
|
+ .decoration({ type: TextDecorationType.LineThrough })
|
|
|
+ }
|
|
|
+ Button('立即开通')
|
|
|
+ .fontSize(14)
|
|
|
.fontColor(Color.White)
|
|
|
.backgroundColor(Color.Red)
|
|
|
- .height(48)
|
|
|
- .width('70%')
|
|
|
- .borderRadius(24)
|
|
|
+ .borderRadius(16)
|
|
|
+ .height(32)
|
|
|
+ .width(80)
|
|
|
+ .margin({ left: 16 })
|
|
|
.onClick(() => {
|
|
|
- this.isLogin = false
|
|
|
- this.userName = '未登录用户'
|
|
|
- this.userAvatar = $r('app.media.icon_person2')
|
|
|
- this.userAvatarUrl = ''
|
|
|
- this.isVip = false
|
|
|
- this.vipExpire = ''
|
|
|
- this.hasActiveSubscription = false;
|
|
|
- this.subscriptionName = '';
|
|
|
- this.subscriptionEndDate = '';
|
|
|
- PreferencesUtil.putSync('isLogin', false);
|
|
|
- PreferencesUtil.putSync('userName', '未登录用户');
|
|
|
- PreferencesUtil.putSync('userAvatarUrl', '');
|
|
|
- PreferencesUtil.putSync('subscriptionName', '');
|
|
|
- PreferencesUtil.putSync('subscriptionEndDate', '');
|
|
|
- PreferencesUtil.putSync('hasActiveSubscription', false);
|
|
|
- ToastUtil.showToast('已退出登录')
|
|
|
- // 这里可以添加退出登录逻辑
|
|
|
- })
|
|
|
- } else {
|
|
|
- Button('登录')
|
|
|
- .fontColor(Color.White)
|
|
|
- .backgroundColor($r('app.color.title_bar_bg'))
|
|
|
- .height(48)
|
|
|
- .width('70%')
|
|
|
- .borderRadius(24)
|
|
|
- .onClick(async () => {
|
|
|
- let req = new wxopensdk.SendAuthReq
|
|
|
- req.isOption1 = false
|
|
|
- req.nonAutomatic = true
|
|
|
- req.scope = 'snsapi_userinfo,snsapi_friend,snsapi_message,snsapi_contact'
|
|
|
- req.state = 'none'
|
|
|
- req.transaction = 'test123'
|
|
|
- let finished = await this.wxApi.sendReq(getContext(this) as common.UIAbilityContext, req)
|
|
|
- console.log('send request finished: ', finished)
|
|
|
+ if (!this.isLogin) {
|
|
|
+ ToastUtil.showToast('请先登录')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 处理购买逻辑
|
|
|
})
|
|
|
}
|
|
|
- Blank().layoutWeight(1)
|
|
|
+ .width('100%')
|
|
|
+ .padding(16)
|
|
|
+ .backgroundColor(Color.White)
|
|
|
+ .borderRadius(12)
|
|
|
+ .margin({ bottom: 12 })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ .margin({ left: 20, right: 20 })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 功能菜单
|
|
|
+ @Builder
|
|
|
+ buildFunctionMenu() {
|
|
|
+ Column() {
|
|
|
+ this.menuItem($r('app.media.icon_favorite'), '我的收藏', () => {
|
|
|
+ if (!this.isLogin) {
|
|
|
+ ToastUtil.showToast('请先登录')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 跳转到收藏页面
|
|
|
+ })
|
|
|
+ Line().width('90%').height(0.5).backgroundColor(0xFFEFEFEF)
|
|
|
+ this.menuItem($r('app.media.icon_history'), '播放历史', () => {
|
|
|
+ if (!this.isLogin) {
|
|
|
+ ToastUtil.showToast('请先登录')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 跳转到历史记录页面
|
|
|
+ })
|
|
|
+ Line().width('90%').height(0.5).backgroundColor(0xFFEFEFEF)
|
|
|
+ this.menuItem($r('app.media.setting'), '设置', () => {
|
|
|
+ // 跳转到设置页面
|
|
|
+ })
|
|
|
+ }
|
|
|
+ .backgroundColor(Color.White)
|
|
|
+ .borderRadius(24)
|
|
|
+ .margin({ left: 20, right: 20, top: 24 })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 登录/退出按钮
|
|
|
+ @Builder
|
|
|
+ buildLoginButton() {
|
|
|
+ Row() {
|
|
|
+ Blank().layoutWeight(1)
|
|
|
+ if (this.isLogin) {
|
|
|
+ Button('退出登录')
|
|
|
+ .fontColor(Color.White)
|
|
|
+ .backgroundColor(Color.Red)
|
|
|
+ .height(48)
|
|
|
+ .width('70%')
|
|
|
+ .borderRadius(24)
|
|
|
+ .onClick(() => {
|
|
|
+ this.isLogin = false
|
|
|
+ this.userName = '未登录用户'
|
|
|
+ this.userAvatar = $r('app.media.icon_person2')
|
|
|
+ this.userAvatarUrl = ''
|
|
|
+ this.isVip = false
|
|
|
+ this.vipExpire = ''
|
|
|
+ this.hasActiveSubscription = false;
|
|
|
+ this.subscriptionName = '';
|
|
|
+ this.subscriptionEndDate = '';
|
|
|
+ PreferencesUtil.putSync('isLogin', false);
|
|
|
+ PreferencesUtil.putSync('userName', '未登录用户');
|
|
|
+ PreferencesUtil.putSync('userAvatarUrl', '');
|
|
|
+ PreferencesUtil.putSync('subscriptionName', '');
|
|
|
+ PreferencesUtil.putSync('subscriptionEndDate', '');
|
|
|
+ PreferencesUtil.putSync('hasActiveSubscription', false);
|
|
|
+ ToastUtil.showToast('已退出登录')
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ Button('登录')
|
|
|
+ .fontColor(Color.White)
|
|
|
+ .backgroundColor($r('app.color.title_bar_bg'))
|
|
|
+ .height(48)
|
|
|
+ .width('70%')
|
|
|
+ .borderRadius(24)
|
|
|
+ .onClick(async () => {
|
|
|
+ let req = new wxopensdk.SendAuthReq
|
|
|
+ req.isOption1 = false
|
|
|
+ req.nonAutomatic = true
|
|
|
+ req.scope = 'snsapi_userinfo,snsapi_friend,snsapi_message,snsapi_contact'
|
|
|
+ req.state = 'none'
|
|
|
+ req.transaction = 'test123'
|
|
|
+ let finished = await this.wxApi.sendReq(getContext(this) as common.UIAbilityContext, req)
|
|
|
+ console.log('send request finished: ', finished)
|
|
|
+ })
|
|
|
}
|
|
|
- .margin({ top: 48, bottom: 0 })
|
|
|
+ Blank().layoutWeight(1)
|
|
|
}
|
|
|
- .backgroundColor(0xFFF6F7FA)
|
|
|
- .width('100%')
|
|
|
- .height('100%')
|
|
|
+ .margin({ top: 48, bottom: 0 })
|
|
|
}
|
|
|
|
|
|
isPhoneLan() {
|