diff --git a/MINE_PAGE_README.md b/MINE_PAGE_README.md new file mode 100644 index 0000000..fbc6e71 --- /dev/null +++ b/MINE_PAGE_README.md @@ -0,0 +1,93 @@ +# "我的"页面功能说明 + +## 功能概述 + +新增了"我的"页面,整合了以下功能: +- 用户信息展示 +- 账户余额查看 +- 预算进度展示 +- 快捷功能入口 +- 退出登录 + +## 页面结构 + +### 1. 用户信息卡片 +- 显示用户头像(emoji) +- 显示用户昵称/用户名 +- 显示用户ID + +### 2. 账户余额卡片(可点击) +- 显示当前账户余额 +- 显示总收入和总支出 +- 点击可跳转到账户管理页面 + +### 3. 预算卡片(可点击) +- 显示本月预算进度条 +- 显示预算金额、已用金额、剩余金额 +- 点击可跳转到预算设置页面 + +### 4. 功能菜单 +- 统计分析:跳转到统计页面 +- 账户管理:跳转到账户管理页面 +- 预算设置:跳转到预算设置页面 + +### 5. 退出登录按钮 +- 点击后弹出确认对话框 +- 确认后清除本地存储并跳转到登录页 + +## 技术特点 + +### 1. 滚动功能 +- 使用 `` 组件实现页面滚动 +- 支持长内容的流畅滚动 +- 底部留有安全区域,避免被导航栏遮挡 + +### 2. 样式设计 +- 延续现有的金色渐变主题风格 +- 使用 rpx 单位,适配不同屏幕尺寸 +- 卡片式布局,清晰美观 +- 添加阴影和圆角,提升视觉效果 + +### 3. 交互体验 +- 卡片点击有视觉反馈(背景色变化) +- 按钮点击有缩放动画 +- 进度条有动画效果 +- 退出登录有二次确认 + +### 4. 数据加载 +- 页面加载时自动获取用户信息、账户信息、预算信息 +- 使用 computed 计算预算进度百分比 +- 错误处理,避免数据加载失败导致页面崩溃 + +## 导航栏配置 + +在 `pages.json` 中添加了: +1. 页面路由配置 +2. TabBar 配置(新增"我的"标签) + +## 图标说明 + +临时使用了 home 图标作为占位符,建议后续替换为专门的"我的"图标。 + +详细说明请查看:`frontend/static/tabbar/ICON_GUIDE.md` + +## 使用方法 + +1. 启动应用后,底部导航栏会显示4个标签:首页、记账、统计、我的 +2. 点击"我的"标签即可进入该页面 +3. 在页面中可以查看账户信息、预算信息,并快速跳转到相关功能页面 + +## 注意事项 + +1. 确保用户已登录,否则用户信息可能显示不完整 +2. 账户和预算数据需要后端API支持 +3. 图标文件需要替换为合适的"我的"图标 +4. 页面使用了 `scroll-view`,确保内容可以正常滚动 + +## 后续优化建议 + +1. 添加更多个人设置选项(如修改密码、修改昵称等) +2. 添加数据统计概览(如本月记账天数、最大单笔支出等) +3. 添加主题切换功能 +4. 添加关于页面和帮助文档入口 +5. 优化用户头像,支持上传自定义头像 diff --git a/api/edit-modal.js b/api/edit-modal.js new file mode 100644 index 0000000..fa64be4 --- /dev/null +++ b/api/edit-modal.js @@ -0,0 +1,23 @@ +import { put } from '../utils/request' + +/** + * 更新账户余额 + * @param {number} initialBalance - 新的初始余额 + * @returns {Promise} + */ +export function updateAccountBalance(initialBalance) { + return put('/accounts/balance', { + initialBalance + }) +} + +/** + * 更新当前月份预算 + * @param {number} amount - 新的预算金额 + * @returns {Promise} + */ +export function updateBudget(amount) { + return put('/budgets/current', { + amount + }) +} diff --git a/api/gold-price.js b/api/gold-price.js new file mode 100644 index 0000000..71714b8 --- /dev/null +++ b/api/gold-price.js @@ -0,0 +1,26 @@ +import { get, post } from '../utils/request' + +// 获取当前黄金价格 +export function getCurrentGoldPrice(goldId = '1053') { + return get('/gold-price/current', { goldId }) +} + +// 获取历史黄金价格 +export function getGoldPriceHistory(goldId = '1053', days = 30) { + return get('/gold-price/history', { goldId, days }) +} + +// 获取指定日期的黄金价格记录 +export function getGoldPricesByDate(goldId = '1053', date) { + return get('/gold-price/by-date', { goldId, date }) +} + +// 获取最近有数据的日期 +export function getLatestGoldPriceDate(goldId = '1053') { + return get('/gold-price/latest-date', { goldId }) +} + +// 立即刷新黄金价格 +export function refreshGoldPrice(goldId = '1053') { + return post('/gold-price/refresh?goldId=' + goldId, {}) +} \ No newline at end of file diff --git a/components/BudgetPieChart/BudgetPieChart.vue b/components/BudgetPieChart/BudgetPieChart.vue index 2337d76..b999b6d 100644 --- a/components/BudgetPieChart/BudgetPieChart.vue +++ b/components/BudgetPieChart/BudgetPieChart.vue @@ -1,182 +1,213 @@ - + + diff --git a/components/EditModal/EditModal.vue b/components/EditModal/EditModal.vue new file mode 100644 index 0000000..8e68106 --- /dev/null +++ b/components/EditModal/EditModal.vue @@ -0,0 +1,278 @@ + + + + + diff --git a/manifest.json b/manifest.json index 550582e..add7dff 100644 --- a/manifest.json +++ b/manifest.json @@ -38,8 +38,42 @@ "" ] }, - "ios" : {}, - "sdkConfigs" : {} + "ios" : { + "dSYMs" : false + }, + "sdkConfigs" : {}, + "icons" : { + "android" : { + "hdpi" : "unpackage/res/icons/72x72.png", + "xhdpi" : "unpackage/res/icons/96x96.png", + "xxhdpi" : "unpackage/res/icons/144x144.png", + "xxxhdpi" : "unpackage/res/icons/192x192.png" + }, + "ios" : { + "appstore" : "unpackage/res/icons/1024x1024.png", + "ipad" : { + "app" : "unpackage/res/icons/76x76.png", + "app@2x" : "unpackage/res/icons/152x152.png", + "notification" : "unpackage/res/icons/20x20.png", + "notification@2x" : "unpackage/res/icons/40x40.png", + "proapp@2x" : "unpackage/res/icons/167x167.png", + "settings" : "unpackage/res/icons/29x29.png", + "settings@2x" : "unpackage/res/icons/58x58.png", + "spotlight" : "unpackage/res/icons/40x40.png", + "spotlight@2x" : "unpackage/res/icons/80x80.png" + }, + "iphone" : { + "app@2x" : "unpackage/res/icons/120x120.png", + "app@3x" : "unpackage/res/icons/180x180.png", + "notification@2x" : "unpackage/res/icons/40x40.png", + "notification@3x" : "unpackage/res/icons/60x60.png", + "settings@2x" : "unpackage/res/icons/58x58.png", + "settings@3x" : "unpackage/res/icons/87x87.png", + "spotlight@2x" : "unpackage/res/icons/80x80.png", + "spotlight@3x" : "unpackage/res/icons/120x120.png" + } + } + } } }, "quickapp" : {}, diff --git a/pages.json b/pages.json index 79340c7..4a04ac6 100644 --- a/pages.json +++ b/pages.json @@ -6,13 +6,6 @@ } }, "pages": [ - { - "path": "pages/login/login", - "style": { - "navigationBarTitleText": "登录", - "navigationStyle": "custom" - } - }, { "path": "pages/index/index", "style": { @@ -32,6 +25,19 @@ "navigationBarTitleText": "统计" } }, + { + "path": "pages/mine/mine", + "style": { + "navigationBarTitleText": "我的" + } + }, + { + "path": "pages/login/login", + "style": { + "navigationBarTitleText": "登录", + "navigationStyle": "custom" + } + }, { "path": "pages/bill/detail", "style": { @@ -49,6 +55,12 @@ "style": { "navigationBarTitleText": "预算管理" } + }, + { + "path": "pages/gold-price/gold-price", + "style": { + "navigationBarTitleText": "黄金价格" + } } ], "tabBar": { @@ -74,6 +86,12 @@ "iconPath": "static/tabbar/statistics.png", "selectedIconPath": "static/tabbar/statistic-active.png", "text": "统计" + }, + { + "pagePath": "pages/mine/mine", + "iconPath": "static/tabbar/mine.png", + "selectedIconPath": "static/tabbar/mine-active.png", + "text": "我的" } ] }, diff --git a/pages/account/account.vue b/pages/account/account.vue index bc4eb0e..05b54a9 100644 --- a/pages/account/account.vue +++ b/pages/account/account.vue @@ -1,302 +1,3 @@ - - - - - + 123 + \ No newline at end of file diff --git a/pages/add/add.vue b/pages/add/add.vue index 7278bdd..831221c 100644 --- a/pages/add/add.vue +++ b/pages/add/add.vue @@ -65,11 +65,12 @@ @input="onAmountInput" @focus="onAmountFocus" /> + 日期 - + {{ form.billDate || '选择日期' }} > @@ -533,57 +534,66 @@ onMounted(() => { height: 100vh; width: 100%; padding-bottom: calc(50px + env(safe-area-inset-bottom)); + background: linear-gradient(135deg, #FFE5CC 0%, #FFD4A8 50%, #FFC08A 100%); } .container { min-height: calc(100vh - 100rpx); - background: #f5f5f5; + background: transparent; padding: 20rpx; padding-bottom: calc(170rpx + env(safe-area-inset-bottom)); } .tabs { display: flex; - background: #fff; - border-radius: 12rpx; + background: rgba(255, 255, 255, 0.9); + border-radius: 20rpx; margin-bottom: 20rpx; padding: 10rpx; + border: 3rpx solid #C8956E; + box-shadow: 0 8rpx 20rpx rgba(200, 149, 110, 0.15); } .tab { flex: 1; text-align: center; padding: 20rpx; - border-radius: 8rpx; - color: #666; + border-radius: 15rpx; + color: #8D6E63; font-size: 28rpx; + font-weight: 600; + transition: all 0.3s; } .tab.active { - background: #667eea; - color: #fff; + background: linear-gradient(135deg, #C8956E, #F5D59E); + color: #5D4037; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.3); } .form { - background: #fff; - border-radius: 12rpx; - padding: 30rpx; + background: rgba(255, 255, 255, 0.95); + border-radius: 25rpx; + padding: 40rpx 30rpx; + border: 3rpx solid #C8956E; + box-shadow: 0 10rpx 30rpx rgba(200, 149, 110, 0.15); } .form-item { - margin-bottom: 30rpx; + margin-bottom: 35rpx; } .label { display: block; font-size: 28rpx; - color: #333; + color: #5D4037; margin-bottom: 20rpx; + font-weight: 600; } .type-selector-compact { display: flex; - gap: 15rpx; + gap: 20rpx; justify-content: center; } @@ -592,32 +602,32 @@ onMounted(() => { flex-direction: column; align-items: center; justify-content: center; - padding: 15rpx 30rpx; - background: #f8f8f8; - border-radius: 8rpx; - border: 2rpx solid transparent; + padding: 20rpx 40rpx; + background: rgba(255, 255, 255, 0.9); + border-radius: 15rpx; + border: 3rpx solid #C8956E; transition: all 0.3s; - min-width: 120rpx; + min-width: 140rpx; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); } .type-option-compact.active { - background: #f0f7ff; - border-color: #667eea; + background: linear-gradient(135deg, #FFD700, #F5D59E); + border-color: #FFD700; + transform: scale(1.05); + box-shadow: 0 8rpx 20rpx rgba(255, 215, 0, 0.3); } .type-icon-compact { - font-size: 32rpx; - margin-bottom: 5rpx; + font-size: 40rpx; + margin-bottom: 8rpx; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.1)); } .type-text-compact { - font-size: 24rpx; - color: #333; -} - -.type-option-compact.active .type-text-compact { - color: #667eea; - font-weight: bold; + font-size: 26rpx; + color: #5D4037; + font-weight: 600; } .category-grid { @@ -636,215 +646,279 @@ onMounted(() => { } .category-icon-circle { - width: 100rpx; - height: 100rpx; + width: 110rpx; + height: 110rpx; border-radius: 50%; - background: #f8f8f8; + background: rgba(255, 255, 255, 0.9); display: flex; align-items: center; justify-content: center; - margin-bottom: 8rpx; - border: 3rpx solid transparent; + margin-bottom: 10rpx; + border: 3rpx solid #C8956E; transition: all 0.3s; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); } .category-icon-item.active .category-icon-circle { - background: #f0f7ff; - border-color: #667eea; - transform: scale(1.1); + background: linear-gradient(135deg, #FFD700, #F5D59E); + border-color: #FFD700; + transform: scale(1.15); + box-shadow: 0 8rpx 20rpx rgba(255, 215, 0, 0.4); } .category-icon-emoji { - font-size: 48rpx; + font-size: 52rpx; line-height: 1; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.1)); } .category-icon-name { font-size: 22rpx; - color: #666; + color: #5D4037; text-align: center; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + font-weight: 500; } .category-icon-item.active .category-icon-name { - color: #667eea; + color: #FFD700; font-weight: bold; + text-shadow: 0 2rpx 4rpx rgba(255, 215, 0, 0.3); } .category-empty { text-align: center; - padding: 40rpx 0; - color: #999; + padding: 50rpx 0; + color: #8D6E63; font-size: 26rpx; + background: rgba(255, 255, 255, 0.5); + border-radius: 15rpx; + border: 2rpx dashed #C8956E; } .input, .textarea { width: 100%; - padding: 20rpx; - background: #f8f8f8; - border-radius: 8rpx; + padding: 25rpx; + background: rgba(255, 255, 255, 0.9); + border-radius: 15rpx; font-size: 28rpx; box-sizing: border-box; - border: none; + border: 3rpx solid #C8956E; outline: none; - -webkit-appearance: none; - -webkit-tap-highlight-color: transparent; - pointer-events: auto; - user-select: text; - -webkit-user-select: text; + color: #5D4037; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); + transition: all 0.3s; +} + +.input:focus, .textarea:focus { + border-color: #FFD700; + box-shadow: 0 0 0 4rpx rgba(255, 215, 0, 0.3), 0 8rpx 25rpx rgba(255, 215, 0, 0.2); +} + +.input::placeholder, .textarea::placeholder { + color: #BCAAA4; } .textarea { - min-height: 200rpx; + min-height: 180rpx; } .category-selector, .picker { display: flex; justify-content: space-between; align-items: center; - padding: 20rpx; - background: #f8f8f8; - border-radius: 8rpx; + padding: 25rpx; + background: rgba(255, 255, 255, 0.9); + border-radius: 15rpx; + border: 3rpx solid #C8956E; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); } .placeholder { - color: #999; + color: #BCAAA4; } .arrow { - color: #999; + color: #C8956E; + font-weight: bold; } .submit-btn { width: 100%; - height: 88rpx; - background: #667eea; - color: #fff; - border-radius: 12rpx; + height: 96rpx; + background: linear-gradient(135deg, #C8956E, #F5D59E, #FFD700); + color: #5D4037; + border-radius: 50rpx; font-size: 32rpx; + font-weight: bold; margin-top: 40rpx; margin-bottom: 20rpx; - border: none; + border: 4rpx solid #5D4037; + box-shadow: 0 10rpx 30rpx rgba(200, 149, 110, 0.4); + transition: all 0.3s; +} + +.submit-btn:active { + transform: scale(0.98); + box-shadow: 0 5rpx 15rpx rgba(200, 149, 110, 0.3); } .ocr-container { - background: #fff; - border-radius: 12rpx; + background: rgba(255, 255, 255, 0.95); + border-radius: 25rpx; padding: 30rpx; + border: 3rpx solid #C8956E; + box-shadow: 0 10rpx 30rpx rgba(200, 149, 110, 0.15); } .image-section { margin-bottom: 30rpx; - background: #fff; - border-radius: 12rpx; + background: rgba(255, 255, 255, 0.8); + border-radius: 20rpx; overflow: hidden; + border: 3rpx solid #C8956E; } .section-header { display: flex; justify-content: space-between; align-items: center; - padding: 20rpx; - background: #f8f8f8; - border-radius: 12rpx; + padding: 25rpx; + background: linear-gradient(135deg, rgba(200, 149, 110, 0.15), rgba(255, 215, 0, 0.15)); + border-radius: 17rpx; cursor: pointer; user-select: none; transition: background 0.3s; } .section-header:active { - background: #f0f0f0; + background: linear-gradient(135deg, rgba(200, 149, 110, 0.25), rgba(255, 215, 0, 0.25)); } .section-title { font-size: 28rpx; font-weight: bold; - color: #333; + color: #5D4037; +} + +.list-title { + font-size: 28rpx; + color: #5D4037; + font-weight: bold; } .section-content { - padding: 20rpx 0; + padding: 25rpx; animation: slideDown 0.3s ease-out; } .upload-area { width: 100%; height: 400rpx; - border: 2rpx dashed #ddd; - border-radius: 12rpx; + border: 3rpx dashed #C8956E; + border-radius: 20rpx; display: flex; align-items: center; justify-content: center; margin-bottom: 30rpx; + background: rgba(255, 255, 255, 0.5); + transition: all 0.3s; +} + +.upload-area:active { + border-color: #FFD700; + background: rgba(255, 215, 0, 0.1); } .preview-image { width: 100%; height: 100%; - border-radius: 12rpx; + border-radius: 17rpx; } .upload-placeholder { text-align: center; - color: #999; + color: #8D6E63; display: flex; flex-direction: column; align-items: center; } .upload-icon { - font-size: 80rpx; + font-size: 100rpx; display: block; margin-bottom: 20rpx; + filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.1)); } .recognize-btn { width: 100%; - height: 88rpx; - background: #19be6b; + height: 96rpx; + background: linear-gradient(135deg, #19BE6B, #51CF66); color: #fff; - border-radius: 12rpx; + border-radius: 50rpx; font-size: 32rpx; + font-weight: bold; margin-bottom: 30rpx; - border: none; + border: 4rpx solid #108043; + box-shadow: 0 10rpx 30rpx rgba(25, 190, 107, 0.3); + transition: all 0.3s; +} + +.recognize-btn:active { + transform: scale(0.98); +} + +.direct-save-btn { + width: 100%; + height: 88rpx; + background: linear-gradient(135deg, #FFD700, #F5D59E); + color: #5D4037; + border-radius: 50rpx; + font-size: 30rpx; + font-weight: bold; + margin-bottom: 20rpx; + border: 3rpx solid #5D4037; + box-shadow: 0 8rpx 25rpx rgba(255, 215, 0, 0.3); + transition: all 0.3s; +} + +.direct-save-btn:active { + transform: scale(0.98); } .ocr-result-list-container { margin-top: 30rpx; - background: #fff; - border-radius: 12rpx; + background: rgba(255, 255, 255, 0.8); + border-radius: 20rpx; overflow: hidden; -} - -.list-title { - font-size: 28rpx; - color: #333; - font-weight: bold; + border: 3rpx solid #C8956E; } .result-list-wrapper { max-height: 600rpx; overflow-y: auto; padding: 0 20rpx 20rpx 20rpx; - -webkit-overflow-scrolling: touch; } .result-card { - background: #fff; - border: 2rpx solid #e0e0e0; - border-radius: 12rpx; - padding: 20rpx; + background: rgba(255, 255, 255, 0.95); + border: 3rpx solid #C8956E; + border-radius: 20rpx; + padding: 25rpx; margin-bottom: 20rpx; transition: all 0.3s; overflow: hidden; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); } .result-card.active { - border-color: #667eea; - background: #f0f7ff; + border-color: #FFD700; + background: linear-gradient(135deg, rgba(255, 215, 0, 0.1), rgba(245, 213, 158, 0.1)); + box-shadow: 0 8rpx 20rpx rgba(255, 215, 0, 0.3); } .result-header { @@ -869,37 +943,37 @@ onMounted(() => { .result-index { font-size: 24rpx; - color: #667eea; + color: #FFD700; font-weight: bold; margin-right: 15rpx; + background: #5D4037; + padding: 6rpx 12rpx; + border-radius: 10rpx; } .result-value.amount.summary { - font-size: 30rpx; + font-size: 32rpx; font-weight: bold; - color: #fa3534; + color: #FA3534; } .result-confidence { font-size: 22rpx; - color: #999; + color: #8D6E63; } .expand-icon { font-size: 24rpx; - color: #667eea; + color: #C8956E; transition: transform 0.3s; margin-left: 10rpx; -} - -.result-card.expanded .expand-icon { - transform: rotate(90deg); + font-weight: bold; } .result-details { - margin-top: 20rpx; - padding-top: 20rpx; - border-top: 1rpx solid #f0f0f0; + margin-top: 25rpx; + padding-top: 25rpx; + border-top: 2rpx solid rgba(200, 149, 110, 0.3); animation: slideDown 0.3s ease-out; } @@ -916,46 +990,54 @@ onMounted(() => { .result-item { display: flex; - padding: 10rpx 0; + padding: 12rpx 0; align-items: center; } .result-label { font-size: 26rpx; - color: #666; + color: #8D6E63; width: 100rpx; flex-shrink: 0; + font-weight: 600; } .result-value { font-size: 28rpx; - color: #333; + color: #5D4037; flex: 1; } .result-value.amount { font-weight: bold; - color: #fa3534; + color: #FA3534; font-size: 32rpx; } .select-btn { width: 100%; - height: 70rpx; - background: #667eea; - color: #fff; - border-radius: 8rpx; - font-size: 26rpx; + height: 76rpx; + background: linear-gradient(135deg, #C8956E, #F5D59E); + color: #5D4037; + border-radius: 50rpx; + font-size: 28rpx; + font-weight: bold; margin-top: 20rpx; - border: none; + border: 3rpx solid #5D4037; display: flex; align-items: center; justify-content: center; + box-shadow: 0 6rpx 18rpx rgba(200, 149, 110, 0.3); + transition: all 0.3s; +} + +.select-btn:active { + transform: scale(0.98); } .ocr-result { margin-top: 30rpx; padding-top: 30rpx; - border-top: 2rpx solid #667eea; + border-top: 3rpx solid #C8956E; } \ No newline at end of file diff --git a/pages/bill/detail.vue b/pages/bill/detail.vue index bbee0f9..2ebdf8d 100644 --- a/pages/bill/detail.vue +++ b/pages/bill/detail.vue @@ -64,7 +64,7 @@ 日期 - + {{ form.billDate || '选择日期' }} > @@ -283,31 +283,36 @@ onLoad((options) => { height: 100vh; width: 100%; padding-bottom: calc(50px + env(safe-area-inset-bottom)); + background: linear-gradient(135deg, #FFE5CC 0%, #FFD4A8 50%, #FFC08A 100%); } .container { min-height: calc(100vh - 100rpx); - background: #f5f5f5; + background: transparent; padding: 20rpx; padding-bottom: calc(170rpx + env(safe-area-inset-bottom)); } .form-card { - background: #fff; - border-radius: 12rpx; - padding: 30rpx; + background: rgba(255, 255, 255, 0.95); + border-radius: 25rpx; + padding: 40rpx 30rpx; + border: 3rpx solid #C8956E; + box-shadow: 0 10rpx 30rpx rgba(93, 64, 55, 0.15); } .form-header { - margin-bottom: 30rpx; - padding-bottom: 20rpx; - border-bottom: 1rpx solid #f0f0f0; + margin-bottom: 35rpx; + padding-bottom: 25rpx; + border-bottom: 3rpx solid rgba(200, 149, 110, 0.3); + text-align: center; } .form-title { - font-size: 36rpx; + font-size: 40rpx; font-weight: bold; - color: #333; + color: #5D4037; + text-shadow: 2rpx 2rpx 0 rgba(255, 215, 0, 0.3); } .form-body { @@ -315,19 +320,20 @@ onLoad((options) => { } .form-item { - margin-bottom: 30rpx; + margin-bottom: 35rpx; } .label { display: block; font-size: 28rpx; - color: #333; + color: #5D4037; margin-bottom: 20rpx; + font-weight: 600; } .type-selector-compact { display: flex; - gap: 15rpx; + gap: 20rpx; justify-content: center; } @@ -336,32 +342,32 @@ onLoad((options) => { flex-direction: column; align-items: center; justify-content: center; - padding: 15rpx 30rpx; - background: #f8f8f8; - border-radius: 8rpx; - border: 2rpx solid transparent; + padding: 20rpx 40rpx; + background: rgba(255, 255, 255, 0.9); + border-radius: 15rpx; + border: 3rpx solid #C8956E; transition: all 0.3s; - min-width: 120rpx; + min-width: 140rpx; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); } .type-option-compact.active { - background: #f0f7ff; - border-color: #667eea; + background: linear-gradient(135deg, #FFD700, #F5D59E); + border-color: #FFD700; + transform: scale(1.05); + box-shadow: 0 8rpx 20rpx rgba(255, 215, 0, 0.3); } .type-icon-compact { - font-size: 32rpx; - margin-bottom: 5rpx; + font-size: 40rpx; + margin-bottom: 8rpx; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.1)); } .type-text-compact { - font-size: 24rpx; - color: #333; -} - -.type-option-compact.active .type-text-compact { - color: #667eea; - font-weight: bold; + font-size: 26rpx; + color: #5D4037; + font-weight: 600; } .category-grid { @@ -380,82 +386,100 @@ onLoad((options) => { } .category-icon-circle { - width: 100rpx; - height: 100rpx; + width: 110rpx; + height: 110rpx; border-radius: 50%; - background: #f8f8f8; + background: rgba(255, 255, 255, 0.9); display: flex; align-items: center; justify-content: center; - margin-bottom: 8rpx; - border: 3rpx solid transparent; + margin-bottom: 10rpx; + border: 3rpx solid #C8956E; transition: all 0.3s; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); } .category-icon-item.active .category-icon-circle { - background: #f0f7ff; - border-color: #667eea; - transform: scale(1.1); + background: linear-gradient(135deg, #FFD700, #F5D59E); + border-color: #FFD700; + transform: scale(1.15); + box-shadow: 0 8rpx 20rpx rgba(255, 215, 0, 0.4); } .category-icon-emoji { - font-size: 48rpx; + font-size: 52rpx; line-height: 1; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.1)); } .category-icon-name { font-size: 22rpx; - color: #666; + color: #5D4037; text-align: center; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + font-weight: 500; } .category-icon-item.active .category-icon-name { - color: #667eea; + color: #FFD700; font-weight: bold; + text-shadow: 0 2rpx 4rpx rgba(255, 215, 0, 0.3); } .category-empty { text-align: center; - padding: 40rpx 0; - color: #999; + padding: 50rpx 0; + color: #8D6E63; font-size: 26rpx; + background: rgba(255, 255, 255, 0.5); + border-radius: 15rpx; + border: 2rpx dashed #C8956E; } .input, .textarea { width: 100%; - padding: 20rpx; - background: #f8f8f8; - border-radius: 8rpx; + padding: 25rpx; + background: rgba(255, 255, 255, 0.9); + border-radius: 15rpx; font-size: 28rpx; box-sizing: border-box; - border: none; + border: 3rpx solid #C8956E; outline: none; - -webkit-appearance: none; - -webkit-tap-highlight-color: transparent; - pointer-events: auto; - user-select: text; - -webkit-user-select: text; + color: #5D4037; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); + transition: all 0.3s; +} + +.input:focus, .textarea:focus { + border-color: #FFD700; + box-shadow: 0 0 0 4rpx rgba(255, 215, 0, 0.3), 0 8rpx 25rpx rgba(255, 215, 0, 0.2); +} + +.input::placeholder, .textarea::placeholder { + color: #BCAAA4; } .textarea { - min-height: 200rpx; + min-height: 180rpx; } .picker { display: flex; justify-content: space-between; align-items: center; - padding: 20rpx; - background: #f8f8f8; - border-radius: 8rpx; + padding: 25rpx; + background: rgba(255, 255, 255, 0.9); + border-radius: 15rpx; + border: 3rpx solid #C8956E; + box-shadow: 0 4rpx 15rpx rgba(200, 149, 110, 0.1); } .arrow { - color: #999; + color: #C8956E; + font-weight: bold; } .form-footer { @@ -466,27 +490,41 @@ onLoad((options) => { .delete-btn { flex: 1; - height: 88rpx; - background: #fa3534; + height: 96rpx; + background: linear-gradient(135deg, #FA3534, #FF6B6B); color: #fff; - border-radius: 12rpx; + border-radius: 50rpx; font-size: 28rpx; - border: none; + font-weight: bold; + border: 3rpx solid #D32F2F; display: flex; align-items: center; justify-content: center; + box-shadow: 0 8rpx 25rpx rgba(250, 53, 52, 0.3); + transition: all 0.3s; +} + +.delete-btn:active { + transform: scale(0.98); } .submit-btn { flex: 2; - height: 88rpx; - background: #667eea; - color: #fff; - border-radius: 12rpx; + height: 96rpx; + background: linear-gradient(135deg, #C8956E, #F5D59E, #FFD700); + color: #5D4037; + border-radius: 50rpx; font-size: 32rpx; - border: none; + font-weight: bold; + border: 4rpx solid #5D4037; display: flex; align-items: center; justify-content: center; + box-shadow: 0 10rpx 30rpx rgba(200, 149, 110, 0.4); + transition: all 0.3s; +} + +.submit-btn:active { + transform: scale(0.98); } diff --git a/pages/budget/budget.vue b/pages/budget/budget.vue index 78e0950..05b54a9 100644 --- a/pages/budget/budget.vue +++ b/pages/budget/budget.vue @@ -1,301 +1,3 @@ - - - - - - + 123 + \ No newline at end of file diff --git a/pages/budget/budget_backup.vue b/pages/budget/budget_backup.vue new file mode 100644 index 0000000..06cb183 --- /dev/null +++ b/pages/budget/budget_backup.vue @@ -0,0 +1,372 @@ + + + + + diff --git a/pages/category/category.vue b/pages/category/category.vue index 5a57724..6f079ef 100644 --- a/pages/category/category.vue +++ b/pages/category/category.vue @@ -162,50 +162,62 @@ onMounted(() => { diff --git a/pages/gold-price/gold-price.vue b/pages/gold-price/gold-price.vue new file mode 100644 index 0000000..4911ee0 --- /dev/null +++ b/pages/gold-price/gold-price.vue @@ -0,0 +1,726 @@ + + + + + diff --git a/pages/index/index.vue b/pages/index/index.vue index 811970c..d1adf5b 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -1,80 +1,80 @@ diff --git a/pages/login/login.vue b/pages/login/login.vue index 65ca3a3..82cee10 100644 --- a/pages/login/login.vue +++ b/pages/login/login.vue @@ -1,66 +1,159 @@ diff --git a/pages/mine/mine.vue b/pages/mine/mine.vue new file mode 100644 index 0000000..98d0200 --- /dev/null +++ b/pages/mine/mine.vue @@ -0,0 +1,586 @@ + + + + + diff --git a/pages/statistics/statistics.vue b/pages/statistics/statistics.vue index 1ff0258..3228a46 100644 --- a/pages/statistics/statistics.vue +++ b/pages/statistics/statistics.vue @@ -122,88 +122,157 @@ onMounted(() => { diff --git a/static/images/logo.png b/static/images/logo.png new file mode 100644 index 0000000..3ab05a1 Binary files /dev/null and b/static/images/logo.png differ diff --git a/static/tabbar/ICON_GUIDE.md b/static/tabbar/ICON_GUIDE.md new file mode 100644 index 0000000..5af7e15 --- /dev/null +++ b/static/tabbar/ICON_GUIDE.md @@ -0,0 +1,39 @@ +# TabBar 图标说明 + +## 需要添加的图标 + +为了让"我的"页面正常显示,你需要添加以下两个图标文件: + +### 1. mine.png(未选中状态) +- 文件路径:`frontend/static/tabbar/mine.png` +- 建议尺寸:81x81 像素 +- 颜色:#7A7E83(灰色) +- 图标内容:用户头像或"我的"相关图标 + +### 2. mine-active.png(选中状态) +- 文件路径:`frontend/static/tabbar/mine-active.png` +- 建议尺寸:81x81 像素 +- 颜色:#667eea(紫色) +- 图标内容:与mine.png相同,但颜色为选中状态 + +## 图标获取方式 + +1. **使用在线图标库** + - iconfont (https://www.iconfont.cn/) + - iconpark (https://iconpark.oceanengine.com/) + +2. **使用设计工具** + - Figma + - Sketch + - Adobe Illustrator + +3. **参考现有图标** + - 可以参考 home.png、add.png、statistics.png 的风格 + - 保持统一的设计风格 + +## 临时解决方案 + +如果暂时没有图标,可以: +1. 复制 home.png 并重命名为 mine.png +2. 复制 home-active.png 并重命名为 mine-active.png +3. 这样至少可以让页面正常运行,之后再替换为合适的图标 diff --git a/static/tabbar/mine-active.png b/static/tabbar/mine-active.png new file mode 100644 index 0000000..96d999c Binary files /dev/null and b/static/tabbar/mine-active.png differ diff --git a/static/tabbar/mine.png b/static/tabbar/mine.png new file mode 100644 index 0000000..ceee161 Binary files /dev/null and b/static/tabbar/mine.png differ diff --git a/utils/crypto.js b/utils/crypto.js new file mode 100644 index 0000000..dcfaffb --- /dev/null +++ b/utils/crypto.js @@ -0,0 +1,56 @@ +// 简单的密码加密/解密工具(Base64编码 + 简单混淆) +// 注意:这不是强加密,只是防止密码明文存储 + +const SECRET_KEY = 'QIANGBAO_AI_JIZHANG_2024' // 密钥 + +/** + * 加密密码 + * @param {string} password - 原始密码 + * @returns {string} - 加密后的密码 + */ +export function encryptPassword(password) { + if (!password) return '' + + try { + // 1. 将密码转为字符数组 + const chars = password.split('') + + // 2. 与密钥进行简单的XOR混淆 + const encrypted = chars.map((char, index) => { + const keyChar = SECRET_KEY[index % SECRET_KEY.length] + return String.fromCharCode(char.charCodeAt(0) ^ keyChar.charCodeAt(0)) + }).join('') + + // 3. Base64编码 + return btoa(unescape(encodeURIComponent(encrypted))) + } catch (error) { + console.error('密码加密失败:', error) + return password // 失败时返回原密码 + } +} + +/** + * 解密密码 + * @param {string} encryptedPassword - 加密的密码 + * @returns {string} - 解密后的密码 + */ +export function decryptPassword(encryptedPassword) { + if (!encryptedPassword) return '' + + try { + // 1. Base64解码 + const decoded = decodeURIComponent(escape(atob(encryptedPassword))) + + // 2. 与密钥进行XOR反混淆 + const chars = decoded.split('') + const decrypted = chars.map((char, index) => { + const keyChar = SECRET_KEY[index % SECRET_KEY.length] + return String.fromCharCode(char.charCodeAt(0) ^ keyChar.charCodeAt(0)) + }).join('') + + return decrypted + } catch (error) { + console.error('密码解密失败:', error) + return '' // 失败时返回空字符串 + } +} diff --git a/utils/request.js b/utils/request.js index b8169ac..c7ec6c7 100644 --- a/utils/request.js +++ b/utils/request.js @@ -1,7 +1,7 @@ // HTTP请求封装 const BASE_URL = process.env.NODE_ENV === 'development' - ? 'http://localhost:8080/api' - : 'https://your-api-domain.com/api' + ? 'http://localhost:12345/api' + : 'https://accounting.aqroid.cn/api' // 获取token function getToken() {