feat: 第一次生产需求文档
This commit is contained in:
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# ---> AL
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
*.app
|
||||||
|
.snapshots/*
|
||||||
33
PRD.md
Normal file
33
PRD.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
## 核心思想
|
||||||
|
名称选择:思投录
|
||||||
|
愿景:让每笔投资都经得起思考
|
||||||
|
副标题:**投资决策与复盘工具**。
|
||||||
|
### 核心功能
|
||||||
|
#### 持仓
|
||||||
|
记录自己的股票持仓,统计各个股票持仓占比,按基金收益法统计的持仓收益。可以基于用户设置的单只股票仓位上限进行预警。
|
||||||
|
#### 交易计划
|
||||||
|
- “计划你的交易,交易你的计划”,让用户可以创建交易计划,选择股票、市场、目标价格、截止时间、投资金额或股份数(两者选一个即可)等。
|
||||||
|
- 之后到目标价后可以提醒用户。
|
||||||
|
- 用户可以为计划设置步骤,默认分三步进行买入等,可以分步设置买入价格。
|
||||||
|
#### 交易记录/复盘
|
||||||
|
- 引导用户记录每一笔交易,可以是从计划中点完成计划等操作跳转到记录页中,也可以是用户主动记录。用户可以记录每一笔交易的企业名称、买卖份数、买卖单价,最重要的是要引导用户写下买卖思考。
|
||||||
|
- 定期弹出页面应到用户写下复盘和思考。
|
||||||
|
- 用户可以参看每一笔交易的附带思考和复盘记录的时间线,让用户可以在交易中学习和成长,类似 QQ 空间的说说功能。
|
||||||
|
- 用户可以分享自己的交易时间线(不确定是否需要)。
|
||||||
|
#### 我的
|
||||||
|
不确定是否应该把 我的 作为一个 Tabbar。
|
||||||
|
- 展示一些我的信息。
|
||||||
|
- 最主要的是一些工具入口,例如 投资检查清单、复利计算器、估值工具(可以分老唐估值法和两段式现金流折现估值法)、自由目标等。
|
||||||
|
- 投资检查清单:可以分为买入和卖出两份检查清单,在每次设置交易计划时最后弹出,让用户每项检查。
|
||||||
|
- 复利计算器:侧重于投资者角度,可以填入初始金额,每年可投入的金额,调整预计的年复合增长率,然后查看未来的总收益。
|
||||||
|
- 自由目标:“让自己有的选”,自由目标可以和复利计算器和持仓结合起来,让用户自己设定一个总资产达成目标。把这个目标和财务自由、赎回自己的时间关联起来,让用户有“奔头”。
|
||||||
|
|
||||||
|
## App名称
|
||||||
|
中文名:思投录
|
||||||
|
英文名:VestMind
|
||||||
|
“Vest”(投资记录与管理)和“Mind”(思考与决策清单)。用户能直观感受到这是一个与“投资”和“思考”相关的工具。
|
||||||
|
Mind”强调了投资不应是冲动行为,而应是经过深思熟虑的、理性的“思维活动”,这与你“让每笔投资都经得起思考”的愿景高度契合。
|
||||||
|
这个词组合起来听起来专业、简洁,且带有一种“智慧投资”的质感,能吸引那些希望提升自己投资决策质量的用户。
|
||||||
|
|
||||||
|
## 主题色
|
||||||
|
主题色需要偏紫色调,注重让人安静思考的色调。
|
||||||
124
README.md
Normal file
124
README.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# 思投录 (VestMind) - 投资决策与复盘工具
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
|
||||||
|
思投录是一款专注于投资决策与复盘的工具应用,旨在"让每笔投资都经得起思考"。本UI设计适用于移动端APP和小程序,采用统一的紫色主题设计风格。
|
||||||
|
|
||||||
|
## 核心功能
|
||||||
|
|
||||||
|
### 1. 持仓管理
|
||||||
|
- 记录股票持仓信息
|
||||||
|
- 统计持仓占比和收益
|
||||||
|
- 基于仓位上限的预警功能
|
||||||
|
- 实时收益展示
|
||||||
|
|
||||||
|
### 2. 交易计划
|
||||||
|
- 创建详细的交易计划
|
||||||
|
- 设置目标价格和截止时间
|
||||||
|
- 分步骤买入计划
|
||||||
|
- 进度跟踪和提醒
|
||||||
|
|
||||||
|
### 3. 交易记录/复盘
|
||||||
|
- 记录每笔交易的详细信息
|
||||||
|
- 交易思考记录
|
||||||
|
- 时间线展示
|
||||||
|
- 定期复盘提醒
|
||||||
|
|
||||||
|
### 4. 我的工具
|
||||||
|
- 投资检查清单
|
||||||
|
- 复利计算器
|
||||||
|
- 估值工具(老唐估值法、现金流折现)
|
||||||
|
- 自由目标规划
|
||||||
|
|
||||||
|
## 设计特色
|
||||||
|
|
||||||
|
### 视觉设计
|
||||||
|
- **主题色**:紫色调(#8b5cf6, #7c3aed),营造安静思考的氛围
|
||||||
|
- **字体**:Inter字体,现代简洁
|
||||||
|
- **布局**:移动端优先,响应式设计
|
||||||
|
- **动效**:微妙的动画效果,提升用户体验
|
||||||
|
|
||||||
|
### 交互设计
|
||||||
|
- 底部导航栏,四个主要功能模块
|
||||||
|
- 模态框设计,支持复杂表单操作
|
||||||
|
- 卡片式布局,信息层次清晰
|
||||||
|
- 时间线展示,直观的交易历史
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
### 文件结构
|
||||||
|
```
|
||||||
|
design-vest-mind/
|
||||||
|
├── index.html # 主页面
|
||||||
|
├── styles.css # 样式文件
|
||||||
|
├── script.js # 交互逻辑
|
||||||
|
└── README.md # 项目说明
|
||||||
|
```
|
||||||
|
|
||||||
|
### 技术栈
|
||||||
|
- **HTML5**:语义化标签,良好的可访问性
|
||||||
|
- **CSS3**:Flexbox布局,CSS Grid,动画效果
|
||||||
|
- **JavaScript**:ES6+语法,模块化设计
|
||||||
|
- **响应式设计**:适配不同屏幕尺寸
|
||||||
|
|
||||||
|
### 兼容性
|
||||||
|
- 移动端浏览器
|
||||||
|
- 微信小程序
|
||||||
|
- iOS Safari
|
||||||
|
- Android Chrome
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
1. 打开 `index.html` 文件即可查看完整UI设计
|
||||||
|
2. 支持所有交互功能,包括:
|
||||||
|
- 页面切换
|
||||||
|
- 数据展示
|
||||||
|
- 模态框操作
|
||||||
|
- 工具计算
|
||||||
|
|
||||||
|
## 设计亮点
|
||||||
|
|
||||||
|
### 1. 紫色主题
|
||||||
|
- 主色调采用紫色渐变,符合"安静思考"的设计理念
|
||||||
|
- 渐变背景和阴影效果,营造层次感
|
||||||
|
|
||||||
|
### 2. 卡片设计
|
||||||
|
- 圆角卡片布局,现代简洁
|
||||||
|
- 悬停效果和阴影,增强交互反馈
|
||||||
|
|
||||||
|
### 3. 数据可视化
|
||||||
|
- 进度条展示计划完成度
|
||||||
|
- 颜色编码区分盈亏状态
|
||||||
|
- 时间线展示交易历史
|
||||||
|
|
||||||
|
### 4. 工具集成
|
||||||
|
- 投资检查清单,帮助理性决策
|
||||||
|
- 复利计算器,规划长期投资
|
||||||
|
- 估值工具,辅助价值判断
|
||||||
|
- 自由目标,激励投资动力
|
||||||
|
|
||||||
|
## 扩展功能
|
||||||
|
|
||||||
|
### 可添加的功能
|
||||||
|
- 数据持久化(LocalStorage)
|
||||||
|
- 图表展示(Chart.js)
|
||||||
|
- 推送通知
|
||||||
|
- 数据导入导出
|
||||||
|
- 多账户管理
|
||||||
|
|
||||||
|
### 小程序适配
|
||||||
|
- 使用微信小程序组件
|
||||||
|
- 适配小程序生命周期
|
||||||
|
- 集成微信API
|
||||||
|
|
||||||
|
## 开发建议
|
||||||
|
|
||||||
|
1. **数据管理**:建议使用状态管理库(如Vuex、Redux)
|
||||||
|
2. **图表展示**:集成ECharts或Chart.js
|
||||||
|
3. **数据持久化**:使用IndexedDB或云数据库
|
||||||
|
4. **性能优化**:懒加载、虚拟滚动
|
||||||
|
5. **测试**:单元测试和端到端测试
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
本UI设计完全基于PRD文档要求,实现了思投录应用的核心功能界面。设计风格现代简洁,交互流畅自然,完全适配移动端和小程序使用场景。紫色主题营造了安静思考的投资氛围,符合"让每笔投资都经得起思考"的产品愿景。
|
||||||
229
index.html
Normal file
229
index.html
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>思投录 - 投资决策与复盘工具</title>
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- 主容器 -->
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<header class="header">
|
||||||
|
<div class="header-content">
|
||||||
|
<h1 class="app-title">思投录</h1>
|
||||||
|
<p class="app-subtitle">让每笔投资都经得起思考</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- 主要内容区域 -->
|
||||||
|
<main class="main-content">
|
||||||
|
<!-- 持仓概览卡片 -->
|
||||||
|
<section class="overview-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2>持仓概览</h2>
|
||||||
|
<span class="total-value">¥128,450.00</span>
|
||||||
|
</div>
|
||||||
|
<div class="portfolio-summary">
|
||||||
|
<div class="summary-item">
|
||||||
|
<span class="label">今日收益</span>
|
||||||
|
<span class="value positive">+¥1,250.00</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-item">
|
||||||
|
<span class="label">总收益率</span>
|
||||||
|
<span class="value positive">+12.5%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 底部导航栏 -->
|
||||||
|
<nav class="bottom-nav">
|
||||||
|
<div class="nav-item active" data-tab="portfolio">
|
||||||
|
<div class="nav-icon">📊</div>
|
||||||
|
<span>持仓</span>
|
||||||
|
</div>
|
||||||
|
<div class="nav-item" data-tab="plans">
|
||||||
|
<div class="nav-icon">📋</div>
|
||||||
|
<span>计划</span>
|
||||||
|
</div>
|
||||||
|
<div class="nav-item" data-tab="records">
|
||||||
|
<div class="nav-icon">📝</div>
|
||||||
|
<span>记录</span>
|
||||||
|
</div>
|
||||||
|
<div class="nav-item" data-tab="tools">
|
||||||
|
<div class="nav-icon">🛠️</div>
|
||||||
|
<span>我的</span>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- 持仓页面 -->
|
||||||
|
<div class="page" id="portfolio-page">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2>我的持仓</h2>
|
||||||
|
<button class="add-btn">+ 添加</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="holdings-list">
|
||||||
|
<div class="holding-item">
|
||||||
|
<div class="stock-info">
|
||||||
|
<div class="stock-name">贵州茅台</div>
|
||||||
|
<div class="stock-code">600519</div>
|
||||||
|
</div>
|
||||||
|
<div class="holding-details">
|
||||||
|
<div class="shares">100股</div>
|
||||||
|
<div class="current-price">¥1,850.00</div>
|
||||||
|
<div class="profit positive">+¥2,500.00 (+15.6%)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="holding-item">
|
||||||
|
<div class="stock-info">
|
||||||
|
<div class="stock-name">腾讯控股</div>
|
||||||
|
<div class="stock-code">00700</div>
|
||||||
|
</div>
|
||||||
|
<div class="holding-details">
|
||||||
|
<div class="shares">200股</div>
|
||||||
|
<div class="current-price">¥320.00</div>
|
||||||
|
<div class="profit negative">-¥800.00 (-1.2%)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 交易计划页面 -->
|
||||||
|
<div class="page hidden" id="plans-page">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2>交易计划</h2>
|
||||||
|
<button class="add-btn">+ 新建</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="plans-list">
|
||||||
|
<div class="plan-item">
|
||||||
|
<div class="plan-header">
|
||||||
|
<div class="stock-info">
|
||||||
|
<div class="stock-name">招商银行</div>
|
||||||
|
<div class="stock-code">600036</div>
|
||||||
|
</div>
|
||||||
|
<div class="plan-status pending">进行中</div>
|
||||||
|
</div>
|
||||||
|
<div class="plan-details">
|
||||||
|
<div class="plan-row">
|
||||||
|
<span class="label">目标价格:</span>
|
||||||
|
<span class="value">¥45.00</span>
|
||||||
|
</div>
|
||||||
|
<div class="plan-row">
|
||||||
|
<span class="label">计划金额:</span>
|
||||||
|
<span class="value">¥10,000</span>
|
||||||
|
</div>
|
||||||
|
<div class="plan-row">
|
||||||
|
<span class="label">截止时间:</span>
|
||||||
|
<span class="value">2024-03-15</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="plan-progress">
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div class="progress-fill" style="width: 60%"></div>
|
||||||
|
</div>
|
||||||
|
<span class="progress-text">已完成 60%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 交易记录页面 -->
|
||||||
|
<div class="page hidden" id="records-page">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2>交易记录</h2>
|
||||||
|
<button class="add-btn">+ 记录</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="timeline">
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-date">2024-01-15</div>
|
||||||
|
<div class="timeline-content">
|
||||||
|
<div class="transaction-card">
|
||||||
|
<div class="transaction-header">
|
||||||
|
<div class="stock-info">
|
||||||
|
<div class="stock-name">贵州茅台</div>
|
||||||
|
<div class="stock-code">600519</div>
|
||||||
|
</div>
|
||||||
|
<div class="transaction-type buy">买入</div>
|
||||||
|
</div>
|
||||||
|
<div class="transaction-details">
|
||||||
|
<div class="detail-row">
|
||||||
|
<span>数量:</span>
|
||||||
|
<span>100股</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-row">
|
||||||
|
<span>价格:</span>
|
||||||
|
<span>¥1,600.00</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="transaction-thoughts">
|
||||||
|
<h4>交易思考:</h4>
|
||||||
|
<p>基于茅台品牌价值和长期增长潜力,认为当前价格具有投资价值。白酒行业龙头地位稳固,现金流优秀。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 我的页面 -->
|
||||||
|
<div class="page hidden" id="tools-page">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2>我的工具</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tools-grid">
|
||||||
|
<div class="tool-card" data-tool="checklist">
|
||||||
|
<div class="tool-icon">✅</div>
|
||||||
|
<div class="tool-name">投资检查清单</div>
|
||||||
|
<div class="tool-desc">买入卖出检查项</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tool-card" data-tool="calculator">
|
||||||
|
<div class="tool-icon">🧮</div>
|
||||||
|
<div class="tool-name">复利计算器</div>
|
||||||
|
<div class="tool-desc">计算未来收益</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tool-card" data-tool="valuation">
|
||||||
|
<div class="tool-icon">📈</div>
|
||||||
|
<div class="tool-name">估值工具</div>
|
||||||
|
<div class="tool-desc">企业价值评估</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tool-card" data-tool="freedom">
|
||||||
|
<div class="tool-icon">🎯</div>
|
||||||
|
<div class="tool-name">自由目标</div>
|
||||||
|
<div class="tool-desc">财务自由规划</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 模态框 -->
|
||||||
|
<div class="modal" id="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 id="modal-title">标题</h3>
|
||||||
|
<button class="close-btn" id="close-modal">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" id="modal-body">
|
||||||
|
<!-- 动态内容 -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
851
script.js
Normal file
851
script.js
Normal file
@@ -0,0 +1,851 @@
|
|||||||
|
// 思投录 - 投资决策与复盘工具
|
||||||
|
class VestMindApp {
|
||||||
|
constructor() {
|
||||||
|
this.currentTab = 'portfolio';
|
||||||
|
this.modal = document.getElementById('modal');
|
||||||
|
this.modalTitle = document.getElementById('modal-title');
|
||||||
|
this.modalBody = document.getElementById('modal-body');
|
||||||
|
this.closeModalBtn = document.getElementById('close-modal');
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.bindEvents();
|
||||||
|
this.showPage('portfolio');
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
bindEvents() {
|
||||||
|
// 底部导航栏事件
|
||||||
|
document.querySelectorAll('.nav-item').forEach(item => {
|
||||||
|
item.addEventListener('click', (e) => {
|
||||||
|
const tab = e.currentTarget.dataset.tab;
|
||||||
|
this.switchTab(tab);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 模态框关闭事件
|
||||||
|
this.closeModalBtn.addEventListener('click', () => {
|
||||||
|
this.hideModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.modal.addEventListener('click', (e) => {
|
||||||
|
if (e.target === this.modal) {
|
||||||
|
this.hideModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 工具卡片点击事件
|
||||||
|
document.querySelectorAll('.tool-card').forEach(card => {
|
||||||
|
card.addEventListener('click', (e) => {
|
||||||
|
const tool = e.currentTarget.dataset.tool;
|
||||||
|
this.openTool(tool);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加按钮事件
|
||||||
|
document.querySelectorAll('.add-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', (e) => {
|
||||||
|
const page = e.currentTarget.closest('.page').id;
|
||||||
|
this.showAddModal(page);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
switchTab(tab) {
|
||||||
|
// 更新导航栏状态
|
||||||
|
document.querySelectorAll('.nav-item').forEach(item => {
|
||||||
|
item.classList.remove('active');
|
||||||
|
});
|
||||||
|
document.querySelector(`[data-tab="${tab}"]`).classList.add('active');
|
||||||
|
|
||||||
|
// 显示对应页面
|
||||||
|
this.showPage(tab);
|
||||||
|
this.currentTab = tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
showPage(pageId) {
|
||||||
|
// 隐藏所有页面
|
||||||
|
document.querySelectorAll('.page').forEach(page => {
|
||||||
|
page.classList.add('hidden');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 显示目标页面
|
||||||
|
const targetPage = document.getElementById(`${pageId}-page`);
|
||||||
|
if (targetPage) {
|
||||||
|
targetPage.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData() {
|
||||||
|
// 模拟数据加载
|
||||||
|
this.loadPortfolioData();
|
||||||
|
this.loadPlansData();
|
||||||
|
this.loadRecordsData();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPortfolioData() {
|
||||||
|
// 模拟持仓数据
|
||||||
|
const holdings = [
|
||||||
|
{
|
||||||
|
name: '贵州茅台',
|
||||||
|
code: '600519',
|
||||||
|
shares: 100,
|
||||||
|
currentPrice: 1850.00,
|
||||||
|
profit: 2500.00,
|
||||||
|
profitRate: 15.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '腾讯控股',
|
||||||
|
code: '00700',
|
||||||
|
shares: 200,
|
||||||
|
currentPrice: 320.00,
|
||||||
|
profit: -800.00,
|
||||||
|
profitRate: -1.2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '招商银行',
|
||||||
|
code: '600036',
|
||||||
|
shares: 500,
|
||||||
|
currentPrice: 42.50,
|
||||||
|
profit: 1250.00,
|
||||||
|
profitRate: 6.2
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
this.renderHoldings(holdings);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderHoldings(holdings) {
|
||||||
|
const container = document.querySelector('.holdings-list');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
container.innerHTML = holdings.map(holding => `
|
||||||
|
<div class="holding-item">
|
||||||
|
<div class="stock-info">
|
||||||
|
<div class="stock-name">${holding.name}</div>
|
||||||
|
<div class="stock-code">${holding.code}</div>
|
||||||
|
</div>
|
||||||
|
<div class="holding-details">
|
||||||
|
<div class="shares">${holding.shares}股</div>
|
||||||
|
<div class="current-price">¥${holding.currentPrice.toFixed(2)}</div>
|
||||||
|
<div class="profit ${holding.profit >= 0 ? 'positive' : 'negative'}">
|
||||||
|
${holding.profit >= 0 ? '+' : ''}¥${holding.profit.toFixed(2)} (${holding.profitRate >= 0 ? '+' : ''}${holding.profitRate}%)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPlansData() {
|
||||||
|
// 模拟交易计划数据
|
||||||
|
const plans = [
|
||||||
|
{
|
||||||
|
name: '招商银行',
|
||||||
|
code: '600036',
|
||||||
|
targetPrice: 45.00,
|
||||||
|
amount: 10000,
|
||||||
|
deadline: '2024-03-15',
|
||||||
|
progress: 60,
|
||||||
|
status: 'pending'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '中国平安',
|
||||||
|
code: '601318',
|
||||||
|
targetPrice: 55.00,
|
||||||
|
amount: 15000,
|
||||||
|
deadline: '2024-04-20',
|
||||||
|
progress: 30,
|
||||||
|
status: 'pending'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
this.renderPlans(plans);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPlans(plans) {
|
||||||
|
const container = document.querySelector('.plans-list');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
container.innerHTML = plans.map(plan => `
|
||||||
|
<div class="plan-item">
|
||||||
|
<div class="plan-header">
|
||||||
|
<div class="stock-info">
|
||||||
|
<div class="stock-name">${plan.name}</div>
|
||||||
|
<div class="stock-code">${plan.code}</div>
|
||||||
|
</div>
|
||||||
|
<div class="plan-status ${plan.status}">进行中</div>
|
||||||
|
</div>
|
||||||
|
<div class="plan-details">
|
||||||
|
<div class="plan-row">
|
||||||
|
<span class="label">目标价格:</span>
|
||||||
|
<span class="value">¥${plan.targetPrice.toFixed(2)}</span>
|
||||||
|
</div>
|
||||||
|
<div class="plan-row">
|
||||||
|
<span class="label">计划金额:</span>
|
||||||
|
<span class="value">¥${plan.amount.toLocaleString()}</span>
|
||||||
|
</div>
|
||||||
|
<div class="plan-row">
|
||||||
|
<span class="label">截止时间:</span>
|
||||||
|
<span class="value">${plan.deadline}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="plan-progress">
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div class="progress-fill" style="width: ${plan.progress}%"></div>
|
||||||
|
</div>
|
||||||
|
<span class="progress-text">已完成 ${plan.progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
loadRecordsData() {
|
||||||
|
// 模拟交易记录数据
|
||||||
|
const records = [
|
||||||
|
{
|
||||||
|
date: '2024-01-15',
|
||||||
|
type: 'buy',
|
||||||
|
name: '贵州茅台',
|
||||||
|
code: '600519',
|
||||||
|
shares: 100,
|
||||||
|
price: 1600.00,
|
||||||
|
thoughts: '基于茅台品牌价值和长期增长潜力,认为当前价格具有投资价值。白酒行业龙头地位稳固,现金流优秀。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-01-10',
|
||||||
|
type: 'sell',
|
||||||
|
name: '比亚迪',
|
||||||
|
code: '002594',
|
||||||
|
shares: 200,
|
||||||
|
price: 280.00,
|
||||||
|
thoughts: '新能源汽车行业竞争加剧,估值偏高,选择获利了结。'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
this.renderRecords(records);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRecords(records) {
|
||||||
|
const container = document.querySelector('.timeline');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
container.innerHTML = records.map(record => `
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-date">${record.date}</div>
|
||||||
|
<div class="timeline-content">
|
||||||
|
<div class="transaction-card">
|
||||||
|
<div class="transaction-header">
|
||||||
|
<div class="stock-info">
|
||||||
|
<div class="stock-name">${record.name}</div>
|
||||||
|
<div class="stock-code">${record.code}</div>
|
||||||
|
</div>
|
||||||
|
<div class="transaction-type ${record.type}">${record.type === 'buy' ? '买入' : '卖出'}</div>
|
||||||
|
</div>
|
||||||
|
<div class="transaction-details">
|
||||||
|
<div class="detail-row">
|
||||||
|
<span>数量:</span>
|
||||||
|
<span>${record.shares}股</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-row">
|
||||||
|
<span>价格:</span>
|
||||||
|
<span>¥${record.price.toFixed(2)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="transaction-thoughts">
|
||||||
|
<h4>交易思考:</h4>
|
||||||
|
<p>${record.thoughts}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
openTool(tool) {
|
||||||
|
switch (tool) {
|
||||||
|
case 'checklist':
|
||||||
|
this.showChecklistModal();
|
||||||
|
break;
|
||||||
|
case 'calculator':
|
||||||
|
this.showCalculatorModal();
|
||||||
|
break;
|
||||||
|
case 'valuation':
|
||||||
|
this.showValuationModal();
|
||||||
|
break;
|
||||||
|
case 'freedom':
|
||||||
|
this.showFreedomModal();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showChecklistModal() {
|
||||||
|
this.modalTitle.textContent = '投资检查清单';
|
||||||
|
this.modalBody.innerHTML = `
|
||||||
|
<div class="checklist-container">
|
||||||
|
<div class="checklist-section">
|
||||||
|
<h4>买入检查清单</h4>
|
||||||
|
<div class="checklist-items">
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>企业基本面是否优秀?</span>
|
||||||
|
</label>
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>估值是否合理?</span>
|
||||||
|
</label>
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>行业前景如何?</span>
|
||||||
|
</label>
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>管理层是否可信?</span>
|
||||||
|
</label>
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>现金流是否健康?</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="checklist-section">
|
||||||
|
<h4>卖出检查清单</h4>
|
||||||
|
<div class="checklist-items">
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>基本面是否恶化?</span>
|
||||||
|
</label>
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>估值是否过高?</span>
|
||||||
|
</label>
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>是否有更好的投资机会?</span>
|
||||||
|
</label>
|
||||||
|
<label class="checklist-item">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span>是否需要资金配置?</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
showCalculatorModal() {
|
||||||
|
this.modalTitle.textContent = '复利计算器';
|
||||||
|
this.modalBody.innerHTML = `
|
||||||
|
<div class="calculator-container">
|
||||||
|
<div class="input-group">
|
||||||
|
<label>初始金额(元)</label>
|
||||||
|
<input type="number" id="initial-amount" placeholder="100000" value="100000">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>每年投入(元)</label>
|
||||||
|
<input type="number" id="annual-investment" placeholder="50000" value="50000">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>年复合增长率(%)</label>
|
||||||
|
<input type="number" id="growth-rate" placeholder="10" value="10" step="0.1">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>投资年限</label>
|
||||||
|
<input type="number" id="years" placeholder="10" value="10">
|
||||||
|
</div>
|
||||||
|
<button class="calculate-btn" onclick="app.calculateCompound()">计算</button>
|
||||||
|
<div class="result-container" id="calculator-result" style="display: none;">
|
||||||
|
<h4>计算结果</h4>
|
||||||
|
<div class="result-item">
|
||||||
|
<span>总投入:</span>
|
||||||
|
<span id="total-investment">¥0</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item">
|
||||||
|
<span>最终金额:</span>
|
||||||
|
<span id="final-amount">¥0</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item">
|
||||||
|
<span>总收益:</span>
|
||||||
|
<span id="total-profit">¥0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateCompound() {
|
||||||
|
const initialAmount = parseFloat(document.getElementById('initial-amount').value) || 0;
|
||||||
|
const annualInvestment = parseFloat(document.getElementById('annual-investment').value) || 0;
|
||||||
|
const growthRate = parseFloat(document.getElementById('growth-rate').value) || 0;
|
||||||
|
const years = parseInt(document.getElementById('years').value) || 0;
|
||||||
|
|
||||||
|
const rate = growthRate / 100;
|
||||||
|
let totalInvestment = initialAmount + annualInvestment * years;
|
||||||
|
let finalAmount = initialAmount * Math.pow(1 + rate, years);
|
||||||
|
|
||||||
|
// 计算每年投入的复利
|
||||||
|
for (let i = 1; i <= years; i++) {
|
||||||
|
finalAmount += annualInvestment * Math.pow(1 + rate, years - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalProfit = finalAmount - totalInvestment;
|
||||||
|
|
||||||
|
document.getElementById('total-investment').textContent = `¥${totalInvestment.toLocaleString()}`;
|
||||||
|
document.getElementById('final-amount').textContent = `¥${finalAmount.toLocaleString()}`;
|
||||||
|
document.getElementById('total-profit').textContent = `¥${totalProfit.toLocaleString()}`;
|
||||||
|
document.getElementById('calculator-result').style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
showValuationModal() {
|
||||||
|
this.modalTitle.textContent = '估值工具';
|
||||||
|
this.modalBody.innerHTML = `
|
||||||
|
<div class="valuation-container">
|
||||||
|
<div class="valuation-tabs">
|
||||||
|
<button class="tab-btn active" data-method="tang">老唐估值法</button>
|
||||||
|
<button class="tab-btn" data-method="dcf">现金流折现</button>
|
||||||
|
</div>
|
||||||
|
<div class="valuation-content">
|
||||||
|
<div class="method-content" id="tang-method">
|
||||||
|
<div class="input-group">
|
||||||
|
<label>净利润(亿元)</label>
|
||||||
|
<input type="number" id="net-profit" placeholder="100" value="100">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>无风险收益率(%)</label>
|
||||||
|
<input type="number" id="risk-free-rate" placeholder="3" value="3" step="0.1">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>合理PE倍数</label>
|
||||||
|
<input type="number" id="pe-ratio" placeholder="25" value="25">
|
||||||
|
</div>
|
||||||
|
<button class="calculate-btn" onclick="app.calculateTangValuation()">计算估值</button>
|
||||||
|
<div class="result-container" id="tang-result" style="display: none;">
|
||||||
|
<h4>估值结果</h4>
|
||||||
|
<div class="result-item">
|
||||||
|
<span>合理估值:</span>
|
||||||
|
<span id="tang-value">¥0亿</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateTangValuation() {
|
||||||
|
const netProfit = parseFloat(document.getElementById('net-profit').value) || 0;
|
||||||
|
const riskFreeRate = parseFloat(document.getElementById('risk-free-rate').value) || 0;
|
||||||
|
const peRatio = parseFloat(document.getElementById('pe-ratio').value) || 0;
|
||||||
|
|
||||||
|
const reasonablePE = 1 / (riskFreeRate / 100);
|
||||||
|
const valuation = netProfit * Math.min(peRatio, reasonablePE);
|
||||||
|
|
||||||
|
document.getElementById('tang-value').textContent = `¥${valuation.toFixed(2)}亿`;
|
||||||
|
document.getElementById('tang-result').style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
showFreedomModal() {
|
||||||
|
this.modalTitle.textContent = '自由目标';
|
||||||
|
this.modalBody.innerHTML = `
|
||||||
|
<div class="freedom-container">
|
||||||
|
<div class="input-group">
|
||||||
|
<label>目标资产(万元)</label>
|
||||||
|
<input type="number" id="target-assets" placeholder="1000" value="1000">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>当前资产(万元)</label>
|
||||||
|
<input type="number" id="current-assets" placeholder="100" value="100">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>年复合增长率(%)</label>
|
||||||
|
<input type="number" id="freedom-growth-rate" placeholder="10" value="10" step="0.1">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>每年投入(万元)</label>
|
||||||
|
<input type="number" id="freedom-annual-investment" placeholder="20" value="20">
|
||||||
|
</div>
|
||||||
|
<button class="calculate-btn" onclick="app.calculateFreedom()">计算达成时间</button>
|
||||||
|
<div class="result-container" id="freedom-result" style="display: none;">
|
||||||
|
<h4>自由目标分析</h4>
|
||||||
|
<div class="result-item">
|
||||||
|
<span>预计达成时间:</span>
|
||||||
|
<span id="freedom-years">0年</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item">
|
||||||
|
<span>届时年龄:</span>
|
||||||
|
<span id="freedom-age">0岁</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item">
|
||||||
|
<span>总投入:</span>
|
||||||
|
<span id="freedom-total-investment">¥0万</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateFreedom() {
|
||||||
|
const targetAssets = parseFloat(document.getElementById('target-assets').value) || 0;
|
||||||
|
const currentAssets = parseFloat(document.getElementById('current-assets').value) || 0;
|
||||||
|
const growthRate = parseFloat(document.getElementById('freedom-growth-rate').value) || 0;
|
||||||
|
const annualInvestment = parseFloat(document.getElementById('freedom-annual-investment').value) || 0;
|
||||||
|
|
||||||
|
const rate = growthRate / 100;
|
||||||
|
let years = 0;
|
||||||
|
let assets = currentAssets;
|
||||||
|
|
||||||
|
// 模拟逐年增长
|
||||||
|
while (assets < targetAssets && years < 50) {
|
||||||
|
assets = assets * (1 + rate) + annualInvestment;
|
||||||
|
years++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalInvestment = currentAssets + annualInvestment * years;
|
||||||
|
const currentAge = 30; // 假设当前年龄
|
||||||
|
const targetAge = currentAge + years;
|
||||||
|
|
||||||
|
document.getElementById('freedom-years').textContent = `${years}年`;
|
||||||
|
document.getElementById('freedom-age').textContent = `${targetAge}岁`;
|
||||||
|
document.getElementById('freedom-total-investment').textContent = `¥${totalInvestment.toFixed(2)}万`;
|
||||||
|
document.getElementById('freedom-result').style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
showAddModal(page) {
|
||||||
|
switch (page) {
|
||||||
|
case 'portfolio-page':
|
||||||
|
this.showAddHoldingModal();
|
||||||
|
break;
|
||||||
|
case 'plans-page':
|
||||||
|
this.showAddPlanModal();
|
||||||
|
break;
|
||||||
|
case 'records-page':
|
||||||
|
this.showAddRecordModal();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showAddHoldingModal() {
|
||||||
|
this.modalTitle.textContent = '添加持仓';
|
||||||
|
this.modalBody.innerHTML = `
|
||||||
|
<div class="form-container">
|
||||||
|
<div class="input-group">
|
||||||
|
<label>股票名称</label>
|
||||||
|
<input type="text" id="stock-name" placeholder="请输入股票名称">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>股票代码</label>
|
||||||
|
<input type="text" id="stock-code" placeholder="请输入股票代码">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>持股数量</label>
|
||||||
|
<input type="number" id="shares" placeholder="请输入持股数量">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>成本价格</label>
|
||||||
|
<input type="number" id="cost-price" placeholder="请输入成本价格" step="0.01">
|
||||||
|
</div>
|
||||||
|
<button class="submit-btn" onclick="app.addHolding()">添加持仓</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
showAddPlanModal() {
|
||||||
|
this.modalTitle.textContent = '新建交易计划';
|
||||||
|
this.modalBody.innerHTML = `
|
||||||
|
<div class="form-container">
|
||||||
|
<div class="input-group">
|
||||||
|
<label>股票名称</label>
|
||||||
|
<input type="text" id="plan-stock-name" placeholder="请输入股票名称">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>股票代码</label>
|
||||||
|
<input type="text" id="plan-stock-code" placeholder="请输入股票代码">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>目标价格</label>
|
||||||
|
<input type="number" id="target-price" placeholder="请输入目标价格" step="0.01">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>计划金额</label>
|
||||||
|
<input type="number" id="plan-amount" placeholder="请输入计划金额">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>截止时间</label>
|
||||||
|
<input type="date" id="deadline">
|
||||||
|
</div>
|
||||||
|
<button class="submit-btn" onclick="app.addPlan()">创建计划</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
showAddRecordModal() {
|
||||||
|
this.modalTitle.textContent = '记录交易';
|
||||||
|
this.modalBody.innerHTML = `
|
||||||
|
<div class="form-container">
|
||||||
|
<div class="input-group">
|
||||||
|
<label>交易类型</label>
|
||||||
|
<select id="transaction-type">
|
||||||
|
<option value="buy">买入</option>
|
||||||
|
<option value="sell">卖出</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>股票名称</label>
|
||||||
|
<input type="text" id="record-stock-name" placeholder="请输入股票名称">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>股票代码</label>
|
||||||
|
<input type="text" id="record-stock-code" placeholder="请输入股票代码">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>交易数量</label>
|
||||||
|
<input type="number" id="record-shares" placeholder="请输入交易数量">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>交易价格</label>
|
||||||
|
<input type="number" id="record-price" placeholder="请输入交易价格" step="0.01">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>交易思考</label>
|
||||||
|
<textarea id="transaction-thoughts" placeholder="请记录您的交易思考..." rows="4"></textarea>
|
||||||
|
</div>
|
||||||
|
<button class="submit-btn" onclick="app.addRecord()">记录交易</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
addHolding() {
|
||||||
|
// 模拟添加持仓
|
||||||
|
this.showToast('持仓添加成功!');
|
||||||
|
this.hideModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
addPlan() {
|
||||||
|
// 模拟添加计划
|
||||||
|
this.showToast('交易计划创建成功!');
|
||||||
|
this.hideModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
addRecord() {
|
||||||
|
// 模拟添加记录
|
||||||
|
this.showToast('交易记录添加成功!');
|
||||||
|
this.hideModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
showModal() {
|
||||||
|
this.modal.classList.add('show');
|
||||||
|
document.body.style.overflow = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
hideModal() {
|
||||||
|
this.modal.classList.remove('show');
|
||||||
|
document.body.style.overflow = 'auto';
|
||||||
|
}
|
||||||
|
|
||||||
|
showToast(message) {
|
||||||
|
// 创建提示框
|
||||||
|
const toast = document.createElement('div');
|
||||||
|
toast.className = 'toast';
|
||||||
|
toast.textContent = message;
|
||||||
|
toast.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
color: white;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
z-index: 10000;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(toast);
|
||||||
|
|
||||||
|
// 显示动画
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.style.opacity = '1';
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// 自动隐藏
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.removeChild(toast);
|
||||||
|
}, 300);
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化应用
|
||||||
|
const app = new VestMindApp();
|
||||||
|
|
||||||
|
// 添加一些额外的样式
|
||||||
|
const additionalStyles = `
|
||||||
|
<style>
|
||||||
|
.checklist-container {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checklist-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checklist-section h4 {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checklist-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checklist-item input[type="checkbox"] {
|
||||||
|
margin-right: 12px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
accent-color: #8b5cf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculator-container,
|
||||||
|
.valuation-container,
|
||||||
|
.freedom-container,
|
||||||
|
.form-container {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group label {
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #374151;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group input,
|
||||||
|
.input-group select,
|
||||||
|
.input-group textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid #d1d5db;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: border-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group input:focus,
|
||||||
|
.input-group select:focus,
|
||||||
|
.input-group textarea:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #8b5cf6;
|
||||||
|
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculate-btn,
|
||||||
|
.submit-btn {
|
||||||
|
width: 100%;
|
||||||
|
background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculate-btn:hover,
|
||||||
|
.submit-btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 3px solid #8b5cf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-container h4 {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-item span:first-child {
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-item span:last-child {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valuation-tabs {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn {
|
||||||
|
flex: 1;
|
||||||
|
padding: 10px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #6b7280;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn.active {
|
||||||
|
color: #8b5cf6;
|
||||||
|
border-bottom-color: #8b5cf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn:hover {
|
||||||
|
color: #8b5cf6;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.head.insertAdjacentHTML('beforeend', additionalStyles);
|
||||||
702
styles.css
Normal file
702
styles.css
Normal file
@@ -0,0 +1,702 @@
|
|||||||
|
/* 基础样式重置 */
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
color: #333;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主容器 */
|
||||||
|
.app-container {
|
||||||
|
max-width: 414px;
|
||||||
|
margin: 0 auto;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f8f9fa;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 顶部导航栏 */
|
||||||
|
.header {
|
||||||
|
background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -50%;
|
||||||
|
left: -50%;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
|
||||||
|
animation: float 6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes float {
|
||||||
|
0%, 100% { transform: translate(-50%, -50%) rotate(0deg); }
|
||||||
|
50% { transform: translate(-50%, -50%) rotate(180deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-title {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.9;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主要内容区域 */
|
||||||
|
.main-content {
|
||||||
|
padding: 20px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 概览卡片 */
|
||||||
|
.overview-card {
|
||||||
|
background: white;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
box-shadow: 0 4px 20px rgba(139, 92, 246, 0.1);
|
||||||
|
border: 1px solid rgba(139, 92, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header h2 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #8b5cf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-summary {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-item {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-item .label {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #6b7280;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-item .value {
|
||||||
|
display: block;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-item .value.positive {
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-item .value.negative {
|
||||||
|
color: #ef4444;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部导航栏 */
|
||||||
|
.bottom-nav {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 100%;
|
||||||
|
max-width: 414px;
|
||||||
|
background: white;
|
||||||
|
border-top: 1px solid #e5e7eb;
|
||||||
|
display: flex;
|
||||||
|
padding: 8px 0;
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item:hover {
|
||||||
|
background: rgba(139, 92, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item.active {
|
||||||
|
background: rgba(139, 92, 246, 0.1);
|
||||||
|
color: #8b5cf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item span {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 页面样式 */
|
||||||
|
.page {
|
||||||
|
padding: 20px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
min-height: calc(100vh - 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header h2 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn {
|
||||||
|
background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 持仓列表 */
|
||||||
|
.holdings-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holding-item {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
border: 1px solid #f3f4f6;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holding-item:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stock-info {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stock-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stock-code {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holding-details {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shares {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-price {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profit {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profit.positive {
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profit.negative {
|
||||||
|
color: #ef4444;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 计划列表 */
|
||||||
|
.plans-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-item {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
border: 1px solid #f3f4f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-status {
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-status.pending {
|
||||||
|
background: rgba(251, 191, 36, 0.1);
|
||||||
|
color: #f59e0b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-status.completed {
|
||||||
|
background: rgba(16, 185, 129, 0.1);
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-details {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-row .label {
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-row .value {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-progress {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
flex: 1;
|
||||||
|
height: 6px;
|
||||||
|
background: #e5e7eb;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, #8b5cf6 0%, #7c3aed 100%);
|
||||||
|
border-radius: 3px;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #6b7280;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 时间线 */
|
||||||
|
.timeline {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 8px;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 2px;
|
||||||
|
background: linear-gradient(180deg, #8b5cf6 0%, #7c3aed 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: -16px;
|
||||||
|
top: 8px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background: #8b5cf6;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid white;
|
||||||
|
box-shadow: 0 0 0 2px #8b5cf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-date {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #6b7280;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-content {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
border: 1px solid #f3f4f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-type {
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-type.buy {
|
||||||
|
background: rgba(16, 185, 129, 0.1);
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-type.sell {
|
||||||
|
background: rgba(239, 68, 68, 0.1);
|
||||||
|
color: #ef4444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-details {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-thoughts {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
border-left: 3px solid #8b5cf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-thoughts h4 {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-thoughts p {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #6b7280;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 工具网格 */
|
||||||
|
.tools-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-card {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
border: 1px solid #f3f4f6;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 8px 24px rgba(139, 92, 246, 0.15);
|
||||||
|
border-color: #8b5cf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-icon {
|
||||||
|
font-size: 32px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-desc {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 模态框 */
|
||||||
|
.modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.show {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background: white;
|
||||||
|
border-radius: 16px;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 400px;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
transform: scale(0.9);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.show .modal-content {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header h3 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #6b7280;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn:hover {
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 375px) {
|
||||||
|
.app-container {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 小程序适配 */
|
||||||
|
@media (max-width: 320px) {
|
||||||
|
.app-title {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item span {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动画效果 */
|
||||||
|
@keyframes slideInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.holding-item,
|
||||||
|
.plan-item,
|
||||||
|
.timeline-content,
|
||||||
|
.tool-card {
|
||||||
|
animation: slideInUp 0.3s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 加载状态 */
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 40px;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading::after {
|
||||||
|
content: '';
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 2px solid #e5e7eb;
|
||||||
|
border-top: 2px solid #8b5cf6;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空状态 */
|
||||||
|
.empty-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px 20px;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state-text {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state-desc {
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
430
产品需求文档.md
Normal file
430
产品需求文档.md
Normal file
@@ -0,0 +1,430 @@
|
|||||||
|
# 思投录 (VestMind) 产品需求文档
|
||||||
|
|
||||||
|
## 1. 产品概述
|
||||||
|
|
||||||
|
### 1.1 产品定位
|
||||||
|
**产品名称**:思投录 (VestMind)
|
||||||
|
**产品定位**:投资决策与复盘工具
|
||||||
|
**产品愿景**:让每笔投资都经得起思考
|
||||||
|
**目标用户**:个人投资者、价值投资者、投资新手
|
||||||
|
|
||||||
|
### 1.2 产品价值
|
||||||
|
- 帮助用户建立系统化的投资决策流程
|
||||||
|
- 通过复盘机制提升投资决策质量
|
||||||
|
- 提供专业的投资工具和检查清单
|
||||||
|
- 培养理性投资思维,避免冲动交易
|
||||||
|
|
||||||
|
### 1.3 设计原则
|
||||||
|
- **紫色主题**:营造安静思考的投资氛围
|
||||||
|
- **移动端优先**:适配APP和小程序
|
||||||
|
- **简洁易用**:降低使用门槛
|
||||||
|
- **数据驱动**:基于数据做决策
|
||||||
|
|
||||||
|
## 2. 功能架构
|
||||||
|
|
||||||
|
### 2.1 核心功能模块
|
||||||
|
```
|
||||||
|
思投录
|
||||||
|
├── 持仓管理
|
||||||
|
├── 交易计划
|
||||||
|
├── 交易记录/复盘
|
||||||
|
└── 我的工具
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 功能优先级
|
||||||
|
- **P0**:持仓管理、交易记录
|
||||||
|
- **P1**:交易计划、基础工具
|
||||||
|
- **P2**:高级工具、分享功能
|
||||||
|
|
||||||
|
## 3. 页面详细设计
|
||||||
|
|
||||||
|
### 3.1 首页/持仓页面
|
||||||
|
|
||||||
|
#### 3.1.1 页面概述
|
||||||
|
用户进入应用后的主页面,展示整体投资概况和持仓详情。
|
||||||
|
|
||||||
|
#### 3.1.2 页面布局
|
||||||
|
```
|
||||||
|
┌─────────────────────────┐
|
||||||
|
│ 思投录 (顶部导航) │
|
||||||
|
│ 让每笔投资都经得起思考 │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 持仓概览卡片 │
|
||||||
|
│ ┌─────────────────────┐ │
|
||||||
|
│ │ 总资产: ¥128,450.00 │ │
|
||||||
|
│ │ 今日收益: +¥1,250 │ │
|
||||||
|
│ │ 总收益率: +12.5% │ │
|
||||||
|
│ └─────────────────────┘ │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 持仓列表 │
|
||||||
|
│ ┌─────────────────────┐ │
|
||||||
|
│ │ 贵州茅台 600519 │ │
|
||||||
|
│ │ 100股 ¥1,850.00 │ │
|
||||||
|
│ │ +¥2,500.00 (+15.6%) │ │
|
||||||
|
│ └─────────────────────┘ │
|
||||||
|
│ ┌─────────────────────┐ │
|
||||||
|
│ │ 腾讯控股 00700 │ │
|
||||||
|
│ │ 200股 ¥320.00 │ │
|
||||||
|
│ │ -¥800.00 (-1.2%) │ │
|
||||||
|
│ └─────────────────────┘ │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 底部导航栏 │
|
||||||
|
│ [持仓] [计划] [记录] [我的] │
|
||||||
|
└─────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.1.3 功能需求
|
||||||
|
|
||||||
|
**持仓概览卡片**
|
||||||
|
- 显示总资产金额
|
||||||
|
- 显示今日收益(正负用颜色区分)
|
||||||
|
- 显示总收益率
|
||||||
|
- 支持点击查看详细统计
|
||||||
|
|
||||||
|
**持仓列表**
|
||||||
|
- 显示股票名称、代码
|
||||||
|
- 显示持股数量、当前价格
|
||||||
|
- 显示盈亏金额和收益率
|
||||||
|
- 支持点击查看单只股票详情
|
||||||
|
- 支持添加新持仓
|
||||||
|
|
||||||
|
**添加持仓功能**
|
||||||
|
- 股票名称输入
|
||||||
|
- 股票代码输入
|
||||||
|
- 持股数量输入
|
||||||
|
- 成本价格输入
|
||||||
|
- 仓位上限设置(预警功能)
|
||||||
|
|
||||||
|
#### 3.1.4 交互需求
|
||||||
|
- 下拉刷新更新数据
|
||||||
|
- 长按持仓项显示操作菜单
|
||||||
|
- 点击"+"按钮添加新持仓
|
||||||
|
- 滑动删除持仓(需确认)
|
||||||
|
|
||||||
|
### 3.2 交易计划页面
|
||||||
|
|
||||||
|
#### 3.2.1 页面概述
|
||||||
|
帮助用户制定和执行交易计划,实现"计划你的交易,交易你的计划"。
|
||||||
|
|
||||||
|
#### 3.2.2 页面布局
|
||||||
|
```
|
||||||
|
┌─────────────────────────┐
|
||||||
|
│ 交易计划 (顶部导航) │
|
||||||
|
│ [+ 新建] │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 计划列表 │
|
||||||
|
│ ┌─────────────────────┐ │
|
||||||
|
│ │ 招商银行 600036 │ │
|
||||||
|
│ │ 状态: 进行中 │ │
|
||||||
|
│ │ 目标价格: ¥45.00 │ │
|
||||||
|
│ │ 计划金额: ¥10,000 │ │
|
||||||
|
│ │ 截止时间: 2024-03-15│ │
|
||||||
|
│ │ ████████░░ 60% │ │
|
||||||
|
│ └─────────────────────┘ │
|
||||||
|
│ ┌─────────────────────┐ │
|
||||||
|
│ │ 中国平安 601318 │ │
|
||||||
|
│ │ 状态: 已完成 │ │
|
||||||
|
│ │ 目标价格: ¥55.00 │ │
|
||||||
|
│ │ 计划金额: ¥15,000 │ │
|
||||||
|
│ │ 截止时间: 2024-04-20│ │
|
||||||
|
│ │ ██████████ 100% │ │
|
||||||
|
│ └─────────────────────┘ │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 底部导航栏 │
|
||||||
|
│ [持仓] [计划] [记录] [我的] │
|
||||||
|
└─────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.2.3 功能需求
|
||||||
|
|
||||||
|
**计划列表**
|
||||||
|
- 显示计划状态(进行中/已完成/已取消)
|
||||||
|
- 显示股票信息、目标价格
|
||||||
|
- 显示计划金额、截止时间
|
||||||
|
- 显示完成进度条
|
||||||
|
- 支持点击查看计划详情
|
||||||
|
|
||||||
|
**新建计划功能**
|
||||||
|
- 股票选择(名称、代码)
|
||||||
|
- 市场选择(A股/港股/美股)
|
||||||
|
- 目标价格设置
|
||||||
|
- 截止时间设置
|
||||||
|
- 投资金额或股份数选择
|
||||||
|
- 分步买入设置(默认3步)
|
||||||
|
- 每步买入价格设置
|
||||||
|
|
||||||
|
**计划执行**
|
||||||
|
- 到达目标价格提醒
|
||||||
|
- 支持手动标记完成
|
||||||
|
- 支持从计划跳转到交易记录
|
||||||
|
- 支持修改计划参数
|
||||||
|
|
||||||
|
#### 3.2.4 交互需求
|
||||||
|
- 点击计划项查看详情
|
||||||
|
- 长按显示操作菜单(编辑/删除/完成)
|
||||||
|
- 滑动标记为完成
|
||||||
|
- 支持计划搜索和筛选
|
||||||
|
|
||||||
|
### 3.3 交易记录/复盘页面
|
||||||
|
|
||||||
|
#### 3.3.1 页面概述
|
||||||
|
记录每笔交易的详细信息,通过时间线展示交易历史和思考过程。
|
||||||
|
|
||||||
|
#### 3.3.2 页面布局
|
||||||
|
```
|
||||||
|
┌─────────────────────────┐
|
||||||
|
│ 交易记录 (顶部导航) │
|
||||||
|
│ [+ 记录] │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 时间线 │
|
||||||
|
│ ┌─────────────────────┐ │
|
||||||
|
│ │ 2024-01-15 │ │
|
||||||
|
│ │ ┌─────────────────┐ │ │
|
||||||
|
│ │ │ 贵州茅台 600519 │ │ │
|
||||||
|
│ │ │ 买入 100股 │ │ │
|
||||||
|
│ │ │ 价格: ¥1,600.00 │ │ │
|
||||||
|
│ │ │ ┌─────────────┐ │ │ │
|
||||||
|
│ │ │ │ 交易思考: │ │ │ │
|
||||||
|
│ │ │ │ 基于茅台品牌 │ │ │ │
|
||||||
|
│ │ │ │ 价值和长期增 │ │ │ │
|
||||||
|
│ │ │ │ 长潜力... │ │ │ │
|
||||||
|
│ │ │ └─────────────┘ │ │ │
|
||||||
|
│ │ └─────────────────┘ │ │
|
||||||
|
│ └─────────────────────┘ │
|
||||||
|
│ ┌─────────────────────┐ │
|
||||||
|
│ │ 2024-01-10 │ │
|
||||||
|
│ │ ┌─────────────────┐ │ │
|
||||||
|
│ │ │ 比亚迪 002594 │ │ │
|
||||||
|
│ │ │ 卖出 200股 │ │ │
|
||||||
|
│ │ │ 价格: ¥280.00 │ │ │
|
||||||
|
│ │ │ ┌─────────────┐ │ │ │
|
||||||
|
│ │ │ │ 交易思考: │ │ │ │
|
||||||
|
│ │ │ │ 新能源汽车行 │ │ │ │
|
||||||
|
│ │ │ │ 业竞争加剧...│ │ │ │
|
||||||
|
│ │ │ └─────────────┘ │ │ │
|
||||||
|
│ │ └─────────────────┘ │ │
|
||||||
|
│ └─────────────────────┘ │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 底部导航栏 │
|
||||||
|
│ [持仓] [计划] [记录] [我的] │
|
||||||
|
└─────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3.3 功能需求
|
||||||
|
|
||||||
|
**时间线展示**
|
||||||
|
- 按时间倒序显示交易记录
|
||||||
|
- 显示交易日期
|
||||||
|
- 显示交易类型(买入/卖出)
|
||||||
|
- 显示股票信息、数量、价格
|
||||||
|
- 显示交易思考内容
|
||||||
|
|
||||||
|
**记录交易功能**
|
||||||
|
- 交易类型选择(买入/卖出)
|
||||||
|
- 股票信息输入
|
||||||
|
- 交易数量输入
|
||||||
|
- 交易价格输入
|
||||||
|
- 交易思考记录(必填)
|
||||||
|
- 支持从计划跳转记录
|
||||||
|
|
||||||
|
**复盘功能**
|
||||||
|
- 定期弹出复盘提醒
|
||||||
|
- 支持为历史交易添加复盘
|
||||||
|
- 复盘内容记录
|
||||||
|
- 复盘时间记录
|
||||||
|
|
||||||
|
**分享功能**(可选)
|
||||||
|
- 支持分享单笔交易
|
||||||
|
- 支持分享交易时间线
|
||||||
|
- 隐私设置控制
|
||||||
|
|
||||||
|
#### 3.3.4 交互需求
|
||||||
|
- 点击交易记录查看详情
|
||||||
|
- 长按显示操作菜单(编辑/删除/复盘)
|
||||||
|
- 支持交易记录搜索
|
||||||
|
- 支持按股票筛选
|
||||||
|
- 支持按时间范围筛选
|
||||||
|
|
||||||
|
### 3.4 我的工具页面
|
||||||
|
|
||||||
|
#### 3.4.1 页面概述
|
||||||
|
提供各种投资工具和计算器,帮助用户做出更好的投资决策。
|
||||||
|
|
||||||
|
#### 3.4.2 页面布局
|
||||||
|
```
|
||||||
|
┌─────────────────────────┐
|
||||||
|
│ 我的工具 (顶部导航) │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 工具网格 │
|
||||||
|
│ ┌─────────┐ ┌─────────┐ │
|
||||||
|
│ │ ✅ │ │ 🧮 │ │
|
||||||
|
│ │投资检查清单│ │复利计算器│ │
|
||||||
|
│ │买入卖出检查│ │计算未来收益│ │
|
||||||
|
│ └─────────┘ └─────────┘ │
|
||||||
|
│ ┌─────────┐ ┌─────────┐ │
|
||||||
|
│ │ 📈 │ │ 🎯 │ │
|
||||||
|
│ │ 估值工具 │ │ 自由目标 │ │
|
||||||
|
│ │企业价值评估│ │财务自由规划│ │
|
||||||
|
│ └─────────┘ └─────────┘ │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 用户信息 │
|
||||||
|
│ ┌─────────────────────┐ │
|
||||||
|
│ │ 头像 | 用户名 │ │
|
||||||
|
│ │ 投资天数: 365天 │ │
|
||||||
|
│ │ 总交易次数: 25次 │ │
|
||||||
|
│ └─────────────────────┘ │
|
||||||
|
├─────────────────────────┤
|
||||||
|
│ 底部导航栏 │
|
||||||
|
│ [持仓] [计划] [记录] [我的] │
|
||||||
|
└─────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4.3 功能需求
|
||||||
|
|
||||||
|
**投资检查清单**
|
||||||
|
- 买入检查清单
|
||||||
|
- 企业基本面是否优秀?
|
||||||
|
- 估值是否合理?
|
||||||
|
- 行业前景如何?
|
||||||
|
- 管理层是否可信?
|
||||||
|
- 现金流是否健康?
|
||||||
|
- 卖出检查清单
|
||||||
|
- 基本面是否恶化?
|
||||||
|
- 估值是否过高?
|
||||||
|
- 是否有更好的投资机会?
|
||||||
|
- 是否需要资金配置?
|
||||||
|
- 支持在创建交易计划时自动弹出
|
||||||
|
|
||||||
|
**复利计算器**
|
||||||
|
- 初始金额输入
|
||||||
|
- 每年投入金额输入
|
||||||
|
- 年复合增长率设置
|
||||||
|
- 投资年限设置
|
||||||
|
- 计算总投入、最终金额、总收益
|
||||||
|
- 生成收益曲线图
|
||||||
|
|
||||||
|
**估值工具**
|
||||||
|
- 老唐估值法
|
||||||
|
- 净利润输入
|
||||||
|
- 无风险收益率设置
|
||||||
|
- 合理PE倍数计算
|
||||||
|
- 估值结果输出
|
||||||
|
- 现金流折现法
|
||||||
|
- 自由现金流输入
|
||||||
|
- 增长率设置
|
||||||
|
- 折现率设置
|
||||||
|
- 估值结果输出
|
||||||
|
|
||||||
|
**自由目标**
|
||||||
|
- 目标资产设置
|
||||||
|
- 当前资产输入
|
||||||
|
- 年复合增长率设置
|
||||||
|
- 每年投入金额设置
|
||||||
|
- 计算达成时间
|
||||||
|
- 与持仓数据联动
|
||||||
|
|
||||||
|
#### 3.4.4 交互需求
|
||||||
|
- 点击工具卡片打开对应工具
|
||||||
|
- 工具界面支持数据输入和计算
|
||||||
|
- 支持结果保存和分享
|
||||||
|
- 支持历史记录查看
|
||||||
|
|
||||||
|
## 4. 技术需求
|
||||||
|
|
||||||
|
### 4.1 平台支持
|
||||||
|
- **移动端APP**:iOS、Android
|
||||||
|
- **小程序**:微信小程序
|
||||||
|
- **响应式设计**:适配不同屏幕尺寸
|
||||||
|
|
||||||
|
### 4.2 数据存储
|
||||||
|
- 本地存储:用户数据、设置
|
||||||
|
- 云端同步:多设备数据同步
|
||||||
|
- 数据备份:定期备份重要数据
|
||||||
|
|
||||||
|
### 4.3 性能要求
|
||||||
|
- 页面加载时间 < 2秒
|
||||||
|
- 操作响应时间 < 500ms
|
||||||
|
- 支持离线使用基础功能
|
||||||
|
|
||||||
|
## 5. 用户体验需求
|
||||||
|
|
||||||
|
### 5.1 易用性
|
||||||
|
- 界面简洁直观
|
||||||
|
- 操作流程简单
|
||||||
|
- 新手引导完善
|
||||||
|
- 错误提示友好
|
||||||
|
|
||||||
|
### 5.2 可访问性
|
||||||
|
- 支持字体大小调节
|
||||||
|
- 支持颜色对比度调节
|
||||||
|
- 支持语音输入
|
||||||
|
- 支持键盘导航
|
||||||
|
|
||||||
|
### 5.3 个性化
|
||||||
|
- 主题颜色自定义
|
||||||
|
- 功能模块自定义
|
||||||
|
- 提醒设置个性化
|
||||||
|
- 数据展示个性化
|
||||||
|
|
||||||
|
## 6. 安全需求
|
||||||
|
|
||||||
|
### 6.1 数据安全
|
||||||
|
- 本地数据加密存储
|
||||||
|
- 网络传输加密
|
||||||
|
- 用户隐私保护
|
||||||
|
- 数据访问权限控制
|
||||||
|
|
||||||
|
### 6.2 功能安全
|
||||||
|
- 重要操作二次确认
|
||||||
|
- 数据删除保护
|
||||||
|
- 异常操作监控
|
||||||
|
- 安全日志记录
|
||||||
|
|
||||||
|
## 7. 运营需求
|
||||||
|
|
||||||
|
### 7.1 数据统计
|
||||||
|
- 用户行为分析
|
||||||
|
- 功能使用统计
|
||||||
|
- 性能监控
|
||||||
|
- 错误日志收集
|
||||||
|
|
||||||
|
### 7.2 用户反馈
|
||||||
|
- 意见反馈入口
|
||||||
|
- 问题报告功能
|
||||||
|
- 用户满意度调查
|
||||||
|
- 功能建议收集
|
||||||
|
|
||||||
|
## 8. 开发计划
|
||||||
|
|
||||||
|
### 8.1 版本规划
|
||||||
|
- **V1.0**:基础功能(持仓、记录)
|
||||||
|
- **V1.1**:交易计划功能
|
||||||
|
- **V1.2**:工具集成
|
||||||
|
- **V2.0**:高级功能和优化
|
||||||
|
|
||||||
|
### 8.2 里程碑
|
||||||
|
- 需求确认:1周
|
||||||
|
- UI设计:2周
|
||||||
|
- 开发实现:8周
|
||||||
|
- 测试优化:2周
|
||||||
|
- 上线发布:1周
|
||||||
|
|
||||||
|
## 9. 成功指标
|
||||||
|
|
||||||
|
### 9.1 用户指标
|
||||||
|
- 日活跃用户数
|
||||||
|
- 用户留存率
|
||||||
|
- 功能使用率
|
||||||
|
- 用户满意度
|
||||||
|
|
||||||
|
### 9.2 产品指标
|
||||||
|
- 交易记录完成率
|
||||||
|
- 计划执行率
|
||||||
|
- 工具使用频率
|
||||||
|
- 数据准确性
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本文档版本:V1.0*
|
||||||
|
*最后更新:2024年1月*
|
||||||
|
*文档状态:待评审*
|
||||||
Reference in New Issue
Block a user