下面是一个完整的家庭园艺种植提醒工具,专为养花爱好者特别是 记忆 力不佳的老年人设计。这个工具可以帮助用户记录植物信息、设置养护周期、接收提醒并记录养护日志。
<!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="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #e6f7ee, #c8e6d5);
color: #333;
line-height: 1.6;
padding: 20px;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
padding: 30px 0;
background: rgba(255, 255, 255, 0.9);
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
}
h1 {
color: #2e7d32;
font-size: 2.8rem;
margin-bottom: 10px;
}
.subtitle {
color: #43a047;
font-size: 1.2rem;
max-width: 700px;
margin: 0 auto;
}
.main-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 25px;
}
@media (max-width: 768px) {
.main-content {
grid-template-columns: 1fr;
}
}
.card {
background: white;
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
padding: 25px;
transition: transform 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
}
.card-title {
color: #2e7d32;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #e0f2e9;
display: flex;
align-items: center;
gap: 10px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #388e3c;
}
input, select {
width: 100%;
padding: 12px 15px;
border: 2px solid #c8e6c9;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s;
}
input:focus, select:focus {
outline: none;
border-color: #4caf50;
box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.2);
}
button {
background: #4caf50;
color: white;
border: none;
padding: 14px 20px;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
width: 100%;
transition: background 0.3s;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}
button:hover {
background: #388e3c;
}
.btn-secondary {
background: #81c784;
}
.btn-secondary:hover {
background: #66bb6a;
}
.plant-list {
max-height: 400px;
overflow-y: auto;
padding-right: 10px;
}
.plant-item {
background: #f1f8e9;
border-radius: 10px;
padding: 15px;
margin-bottom: 15px;
border-left: 4px solid #4caf50;
position: relative;
}
.plant-name {
font-weight: bold;
font-size: 18px;
color: #2e7d32;
margin-bottom: 5px;
}
.plant-detail {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
font-size: 14px;
}
.days-left {
font-weight: bold;
padding: 3px 8px;
border-radius: 12px;
font-size: 12px;
}
.urgent {
background: #ffecb3;
color: #ff9800;
}
.warning {
background: #ffcdd2;
color: #f44336;
}
.normal {
background: #c8e6c9;
color: #2e7d32;
}
.actions {
display: flex;
gap: 10px;
margin-top: 10px;
}
.action-btn {
flex: 1;
padding: 8px;
font-size: 14px;
}
.reminders {
margin-top: 20px;
}
.reminder-item {
background: #fff8e1;
border-radius: 10px;
padding: 15px;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 15px;
border-left: 4px solid #ffc107;
}
.reminder-icon {
font-size: 24px;
color: #ff9800;
}
.log-entry {
padding: 10px 0;
border-bottom: 1px dashed #e0e0e0;
}
.log-time {
font-size: 12px;
color: #757575;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
background: #4caf50;
color: white;
padding: 15px 25px;
border-radius: 8px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
z-index: 1000;
display: flex;
align-items: center;
gap: 10px;
transform: translateX(200%);
transition: transform 0.5s ease;
}
.notification.show {
transform: translateX(0);
}
.empty-state {
text-align: center;
padding: 40px 20px;
color: #757575;
}
.empty-state i {
font-size: 48px;
margin-bottom: 15px;
color: #c8e6c9;
}
footer {
text-align: center;
margin-top: 40px;
padding: 20px;
color: #666;
font-size: 14px;
}
.tabs {
display: flex;
margin-bottom: 20px;
background: #e8f5e9;
border-radius: 10px;
overflow: hidden;
}
.tab {
flex: 1;
padding: 12px;
text-align: center;
cursor: pointer;
transition: background 0.3s;
}
.tab.active {
background: #4caf50;
color: white;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1><i class="fas fa-seedling"></i> 家庭园艺种植提醒工具</h1>
<p class="subtitle">专为爱花人士设计,轻松管理植物养护周期,让您的花园生机勃勃</p>
</header>
<div class="main-content">
<div class="card">
<h2 class="card-title"><i class="fas fa-plus-circle"></i> 添加新植物</h2>
<form id="plant-form">
<div class="form-group">
<label for="plant-name">植物名称</label>
<input type="text" id="plant-name" placeholder="例如:绿萝、月季..." required>
</div>
<div class="form-group">
<label for="plant-type">植物类型</label>
<select id="plant-type">
<option value="flower">花卉</option>
<option value="foliage">观叶植物</option>
<option value="succulent">多肉植物</option>
<option value="herb">香草植物</option>
<option value="vegetable">蔬菜</option>
<option value="tree">树木</option>
</select>
</div>
<div class="form-group">
<label for="plant-date">种植日期</label>
<input type="date" id="plant-date" required>
</div>
<div class="form-group">
<label for="water-cycle">浇水周期 (天)</label>
<input type="number" id="water-cycle" min="1" max="365" value="7" required>
</div>
<div class="form-group">
<label for="fertilizer-cycle">施肥周期 (天)</label>
<input type="number" id="fertilizer-cycle" min="1" max="365" value="30" required>
</div>
<div class="form-group">
<label for="notes">养护备注</label>
<input type="text" id="notes" placeholder="例如:喜阴、需定期修剪...">
</div>
<button type="submit"><i class="fas fa-plus"></i> 添加植物</button>
</form>
<div class="reminders">
<h2 class="card-title"><i class="fas fa-bell"></i> 待办提醒</h2>
<div id="reminders-container">
<!-- 提醒内容将通过JS动态生成 -->
<div class="empty-state">
<i class="fas fa-check-circle"></i>
<p>暂无待办提醒</p>
</div>
</div>
</div>
</div>
<div class="card">
<div class="tabs">
<div class="tab active" data-tab="plants">我的植物</div>
<div class="tab" data-tab="logs">养护日志</div>
</div>
<div class="tab-content active" id="plants-tab">
<h2 class="card-title"><i class="fas fa-leaf"></i> 植物列表</h2>
<div class="plant-list" id="plant-list">
<!-- 植物列表将通过JS动态生成 -->
<div class="empty-state">
<i class="fas fa-seedling"></i>
<p>您尚未添加任何植物</p>
<p>请在左侧添加您的第一株植物</p>
</div>
</div>
</div>
<div class="tab-content" id="logs-tab">
<h2 class="card-title"><i class="fas fa-book"></i> 养护日志</h2>
<div id="log-container">
<!-- 日志内容将通过JS动态生成 -->
<div class="empty-state">
<i class="fas fa-book-open"></i>
<p>暂无养护记录</p>
</div>
</div>
</div>
</div>
</div>
<div class="notification" id="notification">
<i class="fas fa-bell"></i>
<span id="notification-text">提醒内容</span>
</div>
<footer>
<p>家庭园艺种植提醒工具 © 2023 | 让园艺更简单,生活更美好</p>
<p>专为爱花人士设计,特别适合记忆力不佳的老年朋友</p>
</footer>
</div>
<script>
// 示例植物数据
const samplePlants = [
{
id: 1,
name: "绿萝",
type: "foliage",
plantDate: "2023-05-10",
waterCycle: 5,
fertilizerCycle: 30,
notes: "喜阴,避免阳光直射",
lastWatered: "2023-07-15",
lastFertilized: "2023-06-20"
},
{
id: 2,
name: "月季",
type: "flower",
plantDate: "2023-04-22",
waterCycle: 3,
fertilizerCycle: 15,
notes: "需要充足阳光,定期修剪",
lastWatered: "2023-07-17",
lastFertilized: "2023-07-01"
},
{
id: 3,
name: "多肉组合",
type: "succulent",
plantDate: "2023-06-05",
waterCycle: 10,
fertilizerCycle: 60,
notes: "耐旱,宁干勿湿",
lastWatered: "2023-07-10",
lastFertilized: "2023-05-15"
}
];
// 初始化应用
document.addEventListener('DOMContentLoaded', function() {
// 设置默认日期为今天
const today = new Date().toISOString().split('T')[0];
document.getElementById('plant-date').value = today;
// 加载植物数据(优先使用本地存储,否则使用示例数据)
let plants = JSON.parse(localStorage.getItem('gardenPlants')) || samplePlants;
let logs = JSON.parse(localStorage.getItem('gardenLogs')) || [];
// 渲染植物列表
renderPlantList(plants);
// 渲染日志
renderLogs(logs);
// 检查提醒
checkReminders(plants);
// 表单提交事件
document.getElementById('plant-form').addEventListener('submit', function(e) {
e.preventDefault();
addNewPlant(plants, logs);
});
// 标签切换
document.querySelectorAll('.tab').forEach(tab => {
tab.addEventListener('click', function() {
// 移除所有active类
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
// 添加active类到当前标签
this.classList.add('active');
document.getElementById(`${this.dataset.tab}-tab`).classList.add('active');
});
});
});
// 添加新植物
function addNewPlant(plants, logs) {
const name = document.getElementById('plant-name').value;
const type = document.getElementById('plant-type').value;
const plantDate = document.getElementById('plant-date').value;
const waterCycle = parseInt(document.getElementById('water-cycle').value);
const fertilizerCycle = parseInt(document.getElementById('fertilizer-cycle').value);
const notes = document.getElementById('notes').value;
const newPlant = {
id: Date.now(), // 使用时间戳作为ID
name,
type,
plantDate,
waterCycle,
fertilizerCycle,
notes,
lastWatered: plantDate,
lastFertilized: plantDate
};
plants.push(newPlant);
savePlants(plants);
renderPlantList(plants);
// 添加日志
addLog(logs, newPlant.id, newPlant.name, '添加新植物');
renderLogs(logs);
// 重置表单
document.getElementById('plant-form').reset();
document.getElementById('plant-date').value = new Date().toISOString().split('T')[0];
showNotification(`成功添加植物: ${name}`);
}
// 渲染植物列表
function renderPlantList(plants) {
const container = document.getElementById('plant-list');
if (plants.length === 0) {
container.innerHTML = `
<div class="empty-state">
<i class="fas fa-seedling"></i>
<p>您尚未添加任何植物</p>
<p>请在左侧添加您的第一株植物</p>
</div>
`;
return;
}
container.innerHTML = '';
plants.forEach(plant => {
// 计算下次浇水/施肥日期
const nextWater = calculateNextDate(plant.lastWatered, plant.waterCycle);
const nextFertilize = calculateNextDate(plant.lastFertilized, plant.fertilizerCycle);
// 计算剩余天数
const daysToWater = calculateDaysLeft(nextWater);
const daysToFertilize = calculateDaysLeft(nextFertilize);
// 确定状态样式
const waterStatus = getStatusClass(daysToWater);
const fertilizerStatus = getStatusClass(daysToFertilize);
const plantItem = document.createElement('div');
plantItem.className = 'plant-item';
plantItem.innerHTML = `
<div class="plant-name">${plant.name}</div>
<div class="plant-detail">
<span>种植日期:</span>
<span>${formatDate(plant.plantDate)}</span>
</div>
<div class="plant-detail">
<span>浇水周期:</span>
<span>每 ${plant.waterCycle} 天</span>
</div>
<div class="plant-detail">
<span>下次浇水:</span>
<span class="days-left ${waterStatus}">${formatDate(nextWater)} (${daysToWater}天后)</span>
</div>
<div class="plant-detail">
<span>施肥周期:</span>
<span>每 ${plant.fertilizerCycle} 天</span>
</div>
<div class="plant-detail">
<span>下次施肥:</span>
<span class="days-left ${fertilizerStatus}">${formatDate(nextFertilize)} (${daysToFertilize}天后)</span>
</div>
${plant.notes ? `<div class="plant-detail"><span>备注:</span> <span>${plant.notes}</span></div>` : ''}
<div class="actions">
<button class="btn-secondary action-btn" onclick="waterPlant(${plant.id}, '${plant.name}')">
<i class="fas fa-tint"></i> 浇水
</button>
<button class="btn-secondary action-btn" onclick="fertilizePlant(${plant.id}, '${plant.name}')">
<i class="fas fa-flask"></i> 施肥
</button>
<button class="action-btn" onclick="deletePlant(${plant.id}, '${plant.name}')" style="background:#f44336;">
<i class="fas fa-trash"></i>
</button>
</div>
`;
container.appendChild(plantItem);
});
}
// 浇水操作
function waterPlant(id, name) {
const plants = JSON.parse(localStorage.getItem('gardenPlants')) || [];
const plant = plants.find(p => p.id === id);
if (plant) {
plant.lastWatered = new Date().toISOString().split('T')[0];
savePlants(plants);
renderPlantList(plants);
const logs = JSON.parse(localStorage.getItem('gardenLogs')) || [];
addLog(logs, id, name, '浇水');
renderLogs(logs);
showNotification(`已为 ${name} 浇水`);
}
}
// 施肥操作
function fertilizePlant(id, name) {
const plants = JSON.parse(localStorage.getItem('gardenPlants')) || [];
const plant = plants.find(p => p.id === id);
if (plant) {
plant.lastFertilized = new Date().toISOString().split('T')[0];
savePlants(plants);
renderPlantList(plants);
const logs = JSON.parse(localStorage.getItem('gardenLogs')) || [];
addLog(logs, id, name, '施肥');
renderLogs(logs);
showNotification(`已为 ${name} 施肥`);
}
}
// 删除植物
function deletePlant(id, name) {
if (confirm(`确定要删除 ${name} 吗?`)) {
let plants = JSON.parse(localStorage.getItem('gardenPlants')) || [];
plants = plants.filter(p => p.id !== id);
savePlants(plants);
renderPlantList(plants);
showNotification(`已删除植物: ${name}`);
}
}
// 添加日志
function addLog(logs, plantId, plantName, action) {
const now = new Date();
const logEntry = {
id: Date.now(),
plantId,
plantName,
action,
timestamp: now.toISOString()
};
logs.unshift(logEntry);
saveLogs(logs);
}
// 渲染日志
function renderLogs(logs) {
const container = document.getElementById('log-container');
if (logs.length === 0) {
container.innerHTML = `
<div class="empty-state">
<i class="fas fa-book-open"></i>
<p>暂无养护记录</p>
</div>
`;
return;
}
container.innerHTML = '';
// 只显示最近的20条日志
const recentLogs = logs.slice(0, 20);
recentLogs.forEach(log => {
const logEntry = document.createElement('div');
logEntry.className = 'log-entry';
logEntry.innerHTML = `
<div><strong>${log.plantName}</strong> - ${log.action}</div>
<div class="log-time">${formatDateTime(log.timestamp)}</div>
`;
container.appendChild(logEntry);
});
}
// 检查提醒
function checkReminders(plants) {
const container = document.getElementById('reminders-container');
container.innerHTML = '';
const now = new Date();
let hasReminders = false;
plants.forEach(plant => {
const nextWater = calculateNextDate(plant.lastWatered, plant.waterCycle);
const nextFertilize = calculateNextDate(plant.lastFertilized, plant.fertilizerCycle);
const daysToWater = calculateDaysLeft(nextWater);
const daysToFertilize = calculateDaysLeft(nextFertilize);
// 如果需要在3天内浇水或施肥,则显示提醒
if (daysToWater <= 3 && daysToWater >= 0) {
hasReminders = true;
const reminder = createReminderElement(
plant.name,
'浇水',
daysToWater,
nextWater,
plant.id
);
container.appendChild(reminder);
}
if (daysToFertilize <= 3 && daysToFertilize >= 0) {
hasReminders = true;
const reminder = createReminderElement(
plant.name,
'施肥',
daysToFertilize,
nextFertilize,
plant.id
);
container.appendChild(reminder);
}
});
if (!hasReminders) {
container.innerHTML = `
<div class="empty-state">
<i class="fas fa-check-circle"></i>
<p>暂无待办提醒</p>
</div>
`;
}
}
// 创建提醒元素
function createReminderElement(plantName, action, daysLeft, dueDate, plantId) {
const reminder = document.createElement('div');
reminder.className = 'reminder-item';
reminder.innerHTML = `
<div class="reminder-icon">
<i class="fas fa-exclamation-circle"></i>
</div>
<div>
<strong>${plantName}</strong> 需要${action}了!
<div>剩余时间: ${daysLeft}天 (${formatDate(dueDate)})</div>
</div>
<button class="btn-secondary" onclick="${action === '浇水' ? `waterPlant(${plantId}, '${plantName}')` : `fertilizePlant(${plantId}, '${plantName}')`}" style="margin-left:auto;width:auto;padding:8px 15px;">
<i class="fas fa-${action === '浇水' ? 'tint' : 'flask'}"></i> 立即${action}
</button>
`;
return reminder;
}
// 辅助函数:计算下次日期
function calculateNextDate(lastDate, cycle) {
const date = new Date(lastDate);
date.setDate(date.getDate() + cycle);
return date.toISOString().split('T')[0];
}
// 辅助函数:计算剩余天数
function calculateDaysLeft(targetDate) {
const target = new Date(targetDate);
const now = new Date();
const diffTime = target - now;
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}
// 辅助函数:获取状态类名
function getStatusClass(daysLeft) {
if (daysLeft <= 0) return 'warning'; // 过期
if (daysLeft <= 2) return 'urgent'; // 紧急
return 'normal'; // 正常
}
// 辅助函数:格式化日期
function formatDate(dateString) {
const options = { year: 'numeric', month: 'long', day: 'numeric' };
return new Date(dateString).toLocaleDateString('zh-CN', options);
}
// 辅助函数:格式化日期和时间
function formatDateTime(dateTimeString) {
const date = new Date(dateTimeString);
return `${date.getFullYear()}-${(date.getMonth()+1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
}
// 辅助函数:显示通知
function showNotification(message) {
const notification = document.getElementById('notification');
const notificationText = document.getElementById('notification-text');
notificationText.textContent = message;
notification.classList.add('show');
setTimeout(() => {
notification.classList.remove('show');
}, 3000);
}
// 保存植物数据
function savePlants(plants) {
localStorage.setItem('gardenPlants', JSON.stringify(plants));
}
// 保存日志数据
function saveLogs(logs) {
localStorage.setItem('gardenLogs', JSON.stringify(logs));
}
</script>
</body>
</html>
这个家庭园艺种植提醒工具具有以下核心功能:
植物信息管理
添加新植物(名称、类型、种植日期)
设置浇水周期和施肥周期
添加养护备注
查看所有植物列表及详细信息
智能提醒系统
自动计算下次浇水/施肥日期
根据剩余天数显示不同状态(正常/紧急/过期)
提前3天显示待办提醒
一键完成浇水/施肥操作
养护日志记录
自动记录所有养护操作(添加、浇水、施肥)
按时间倒序显示最近20条记录
显示操作时间和具体动作
用户友好设计
大字体和清晰布局,适合老年人使用
直观的状态颜色标识(绿色正常,橙色紧急,红色过期)
响应式设计,适配各种设备屏幕
本地存储数据,关闭页面不会丢失信息
在左侧表单中输入植物信息
设置合适的浇水和施肥周期(单位:天)
点击"添加植物"按钮保存信息
在主界面查看所有植物及其养护状态
当收到提醒时,点击"立即浇水"或"立即施肥"按钮记录操作
在"养护日志"标签页查看所有历史操作记录
这个工具特别适合记忆力不佳的老年园艺爱好者,帮助他们轻松管理多种植物的养护周期,确保植物健康生长。
我是编程小白,请大家多多指教,谢谢!
相关知识
家庭园艺种植提醒工具,核心功能,录入植物名称,比如绿萝,月季等,种植日期,设置浇水周期,施肥周期,到点自动弹出提醒,记录养护日志,应用场景,养花爱好者,尤其是记性不好的老年人,让植物养得更茂盛。
植物浇水提醒 app下载 植物浇水提醒(每日浇水提醒工具)v2.3.0安卓版 下载
养花如何做到科学养花?园艺师教你,使用园艺标签记录花卉时间
智能花盆定制:打造个性化养花助手,解锁绿植养护新体验
生态种植app免费下载
绿手指下载
5款最佳花草种植记录APP,助你轻松管理家庭园艺
花卉养殖软件推荐:提高种植效率的数字化工具
为园艺爱好者打造的安卓应用:Allt om Trädgård园艺管理工具
苹果养花app下载
网址: 家庭园艺种植提醒工具,核心功能,录入植物名称,比如绿萝,月季等,种植日期,设置浇水周期,施肥周期,到点自动弹出提醒,记录养护日志,应用场景,养花爱好者,尤其是记性不好的老年人,让植物养得更茂盛。 https://m.huajiangbk.com/newsview2599123.html
| 上一篇: 被名字耽误的仙女花:重瓣耧斗菜的 |
下一篇: 金枝玉叶水培 水培金枝玉叶养护指 |