第一次上传

This commit is contained in:
xxk
2026-06-11 09:53:11 +08:00
commit e257f2009e
89 changed files with 4336 additions and 0 deletions
+255
View File
@@ -0,0 +1,255 @@
<template>
<view class="app-page" :class="themeClass">
<view class="surface-card page-hero">
<text class="hero-kicker">ACCOUNT</text>
<text class="hero-title">账户资料</text>
<text class="hero-desc">管理本地昵称显示资料与本机记账模式说明</text>
<view class="hero-tags">
<text class="hero-tag">本地资料</text>
<text class="hero-tag soft">本地存储</text>
</view>
</view>
<section-card title="昵称设置" subtitle="修改后仅用于个人页展示和首字头像,不参与账单计算">
<view class="profile-card surface-strong">
<view class="avatar-shell">{{ avatarText }}</view>
<view class="profile-body">
<text class="profile-name">{{ profileName }}</text>
<text class="profile-meta">当前昵称仅保存在本地设备可随时修改</text>
</view>
<view class="status-badge">本地</view>
</view>
<view class="editor-block">
<view class="input-shell">
<input v-model="nicknameInput" maxlength="12" placeholder="请输入昵称" />
</view>
<text class="tiny-text editor-tip">留空时页面会统一显示用户</text>
</view>
<view class="action-row">
<view class="ghost-button" @click="clearNickname">清空昵称</view>
<view class="primary-button" @click="saveNickname">保存昵称</view>
</view>
</section-card>
<section-card title="显示与模式" subtitle="集中展示当前账户页的生效状态">
<view class="info-list">
<view class="info-item surface-strong">
<view>
<text class="info-title">昵称首字头像</text>
<text class="info-desc">当前显示 {{ avatarText }}自动根据昵称生成</text>
</view>
<text class="info-mark">已启用</text>
</view>
<view class="info-item surface-strong">
<view>
<text class="info-title">本机记账模式</text>
<text class="info-desc">账单与预算默认仅保存在当前设备本地</text>
</view>
<text class="info-mark">默认</text>
</view>
</view>
</section-card>
<section-card title="使用提示" subtitle="帮助用户理解昵称显示与数据边界">
<view class="tips-card surface-strong">
<view v-for="(tip, index) in tips" :key="tip" class="tip-row">
<text class="tip-index">0{{ index + 1 }}</text>
<text class="tip-line">{{ tip }}</text>
</view>
</view>
</section-card>
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue'
import SectionCard from '../../../components/SectionCard.vue'
import { useAppStore } from '../../../utils/store'
const store = useAppStore()
const themeClass = computed(() => (store.state.settings.theme === 'dark' ? 'theme-dark' : ''))
const profileName = computed(() => store.state.settings.profile.nickname || '用户')
const avatarText = computed(() => profileName.value.slice(0, 1))
const nicknameInput = ref(store.state.settings.profile.nickname || '')
const tips = [
'昵称仅用于个人页展示和首字头像,不参与账单计算。',
'账单、预算和设置默认不会自动上传云端。',
'如需更换设备,请先在“备份与恢复”页面导出 JSON 备份。'
]
watch(
() => store.state.settings.profile.nickname,
(value) => {
nicknameInput.value = value || ''
}
)
function saveNickname() {
const nextName = nicknameInput.value.trim()
store.setProfile({
authorized: false,
nickname: nextName,
avatarUrl: ''
})
uni.showToast({ title: '昵称已保存', icon: 'none' })
}
function clearNickname() {
nicknameInput.value = ''
store.setProfile({
authorized: false,
nickname: '',
avatarUrl: ''
})
uni.showToast({ title: '昵称已清空', icon: 'none' })
}
</script>
<style lang="scss" scoped>
.page-hero {
padding: 30rpx;
background: linear-gradient(145deg, rgba(16, 42, 67, 0.96) 0%, rgba(31, 111, 95, 0.92) 100%);
color: #ffffff;
}
.hero-kicker,
.hero-desc,
.hero-tag.soft {
color: rgba(255, 255, 255, 0.76);
}
.hero-kicker {
font-size: 20rpx;
letter-spacing: 4rpx;
}
.hero-title {
display: block;
margin-top: 12rpx;
font-size: 44rpx;
font-weight: 700;
}
.hero-desc {
display: block;
margin-top: 14rpx;
font-size: 24rpx;
line-height: 1.7;
}
.hero-tags {
display: flex;
flex-wrap: wrap;
gap: 14rpx;
margin-top: 22rpx;
}
.hero-tag {
padding: 12rpx 18rpx;
border-radius: 999rpx;
background: rgba(255, 255, 255, 0.16);
font-size: 22rpx;
}
.profile-card,
.info-item,
.action-row,
.tip-row {
display: flex;
align-items: center;
gap: 16rpx;
}
.profile-card,
.tips-card {
padding: 26rpx;
border-radius: 28rpx;
}
.avatar-shell {
width: 108rpx;
height: 108rpx;
border-radius: 32rpx;
background: var(--bg-accent);
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
font-weight: 700;
box-shadow: 0 18rpx 32rpx rgba(16, 42, 67, 0.16);
}
.profile-body {
flex: 1;
}
.profile-name,
.info-title {
display: block;
font-size: 31rpx;
font-weight: 700;
color: var(--text-primary);
}
.profile-meta,
.info-desc,
.tip-line {
display: block;
margin-top: 10rpx;
font-size: 24rpx;
line-height: 1.7;
color: var(--text-secondary);
}
.status-badge,
.info-mark {
padding: 10rpx 18rpx;
border-radius: 999rpx;
background: var(--brand-soft);
font-size: 22rpx;
color: var(--brand);
}
.editor-block {
margin-top: 18rpx;
}
.editor-tip {
display: block;
margin-top: 12rpx;
}
.action-row {
margin-top: 18rpx;
}
.action-row .ghost-button,
.action-row .primary-button {
flex: 1;
}
.info-list {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.info-item {
justify-content: space-between;
padding: 24rpx;
border-radius: 26rpx;
}
.tip-row {
align-items: flex-start;
padding: 12rpx 0;
}
.tip-index {
width: 56rpx;
font-size: 24rpx;
font-weight: 700;
color: var(--brand);
}
</style>