feat: 添加设计文件packages
This commit is contained in:
851
packages/design-ui/script.js
Normal file
851
packages/design-ui/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);
|
||||
Reference in New Issue
Block a user