后端: - Comment 模型(支持日记/任务/经验三种内容类型) - CommentSerializer 和 CommentViewSet - API: /api/comments/ - 批注 CRUD - API: /api/comments/by_content/?content_type=diary&object_id=1 - 按内容获取批注 - 日记/任务/经验序列化器嵌套显示批注 前端: - 批注样式(comments-section, comment-item) - 添加批注输入框 使用方式: - 北极星可以在任何日记/任务/经验下添加批注 - 批注会显示在内容下方 - 支持查看历史批注
173 lines
6.7 KiB
Python
Executable File
173 lines
6.7 KiB
Python
Executable File
from django.db import models
|
|
from django.utils import timezone
|
|
|
|
class DiaryEntry(models.Model):
|
|
"""日记条目 - 作为所有记录的主入口"""
|
|
date = models.DateField('日期', unique=True)
|
|
title = models.CharField('标题', max_length=200, default='每日日记')
|
|
content = models.TextField('日记内容', blank=True, default='')
|
|
completed_tasks = models.TextField('完成的任务', blank=True, default='')
|
|
learned = models.TextField('学到的东西', blank=True, default='')
|
|
problems = models.TextField('遇到的问题和解决方案', blank=True, default='')
|
|
reflections = models.TextField('想法和反思', blank=True, default='')
|
|
improvements = models.TextField('进步点', blank=True, default='')
|
|
plans = models.TextField('明日计划', blank=True, default='')
|
|
|
|
# 关联字段(使用字符串引用避免循环导入)
|
|
linked_tasks = models.ManyToManyField('Task', blank=True, related_name='diary_entries', verbose_name='关联任务')
|
|
created_at = models.DateTimeField('创建时间', auto_now_add=True)
|
|
updated_at = models.DateTimeField('更新时间', auto_now=True)
|
|
|
|
class Meta:
|
|
ordering = ['-date']
|
|
verbose_name = '日记'
|
|
verbose_name_plural = '日记'
|
|
|
|
def __str__(self):
|
|
return f"{self.date} - {self.title}"
|
|
|
|
def link_task(self, task, progress_percent=None, notes=''):
|
|
"""关联任务并更新进展"""
|
|
self.linked_tasks.add(task)
|
|
if progress_percent is not None:
|
|
task.update_progress(progress_percent, f"日记 {self.date}: {notes}")
|
|
self.save()
|
|
|
|
def extract_experience(self, title, category, problem, solution, lesson_learned=''):
|
|
"""从日记提炼经验"""
|
|
exp = Experience.objects.create(
|
|
title=title,
|
|
category=category,
|
|
problem=problem,
|
|
solution=solution,
|
|
lesson_learned=lesson_learned,
|
|
date=self.date
|
|
)
|
|
return exp
|
|
|
|
|
|
class Experience(models.Model):
|
|
"""经验总结 - 记录遇到的问题和解决方法"""
|
|
title = models.CharField('标题', max_length=200)
|
|
category = models.CharField('类别', max_length=50, choices=[
|
|
('deployment', '📦 部署'),
|
|
('development', '💻 开发'),
|
|
('database', '🗄️ 数据库'),
|
|
('permission', '🔐 权限'),
|
|
('network', '🌐 网络'),
|
|
('other', '其他'),
|
|
])
|
|
problem = models.TextField('问题描述')
|
|
solution = models.TextField('解决方案')
|
|
lesson_learned = models.TextField('经验教训', blank=True, default='')
|
|
date = models.DateField('日期')
|
|
|
|
# 关联到日记(可选,经验可以独立创建)
|
|
extracted_from = models.ForeignKey(DiaryEntry, on_delete=models.SET_NULL, null=True, blank=True,
|
|
related_name='experiences', verbose_name='提取自日记')
|
|
created_at = models.DateTimeField('创建时间', auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = ['-date', '-created_at']
|
|
verbose_name = '经验总结'
|
|
verbose_name_plural = '经验总结'
|
|
|
|
def __str__(self):
|
|
return f"{self.category} - {self.title}"
|
|
|
|
|
|
class DailyProgress(models.Model):
|
|
"""每日进度追踪"""
|
|
entry = models.ForeignKey(DiaryEntry, on_delete=models.CASCADE, related_name='progresses')
|
|
category = models.CharField('类别', max_length=50)
|
|
description = models.TextField('描述')
|
|
progress_percent = models.IntegerField('进度百分比', default=0)
|
|
created_at = models.DateTimeField('创建时间', auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = ['-created_at']
|
|
verbose_name = '进度'
|
|
verbose_name_plural = '进度'
|
|
|
|
def __str__(self):
|
|
return f"{self.entry.date} - {self.category}: {self.progress_percent}%"
|
|
|
|
|
|
class Comment(models.Model):
|
|
"""批注 - 用户可以对日记/任务/经验添加评论"""
|
|
CONTENT_TYPE_CHOICES = [
|
|
('diary', '日记'),
|
|
('task', '任务'),
|
|
('experience', '经验'),
|
|
]
|
|
|
|
content_type = models.CharField('内容类型', max_length=20, choices=CONTENT_TYPE_CHOICES)
|
|
object_id = models.IntegerField('内容 ID')
|
|
content = models.TextField('批注内容')
|
|
created_by = models.CharField('创建者', max_length=100, default='北极星')
|
|
created_at = models.DateTimeField('创建时间', auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = ['-created_at']
|
|
verbose_name = '批注'
|
|
verbose_name_plural = '批注'
|
|
|
|
def __str__(self):
|
|
return f"{self.content_type} #{self.object_id} - {self.created_by}"
|
|
|
|
|
|
class Task(models.Model):
|
|
"""工作任务 - 跟踪任务和进展"""
|
|
STATUS_CHOICES = [
|
|
('pending', '⏳ 待开始'),
|
|
('in_progress', '🔄 进行中'),
|
|
('blocked', '🚧 已阻塞'),
|
|
('completed', '✅ 已完成'),
|
|
('cancelled', '❌ 已取消'),
|
|
]
|
|
|
|
PRIORITY_CHOICES = [
|
|
('low', '低'),
|
|
('medium', '中'),
|
|
('high', '高'),
|
|
('critical', '紧急'),
|
|
]
|
|
|
|
title = models.CharField('任务标题', max_length=200)
|
|
description = models.TextField('任务描述', blank=True, default='')
|
|
status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='pending')
|
|
priority = models.CharField('优先级', max_length=20, choices=PRIORITY_CHOICES, default='medium')
|
|
progress_percent = models.IntegerField('进展百分比', default=0)
|
|
progress_notes = models.TextField('进展记录', blank=True, default='')
|
|
assigned_to = models.CharField('负责人', max_length=100, blank=True, default='码神')
|
|
due_date = models.DateField('截止日期', null=True, blank=True)
|
|
completed_at = models.DateTimeField('完成时间', null=True, blank=True)
|
|
created_at = models.DateTimeField('创建时间', auto_now_add=True)
|
|
updated_at = models.DateTimeField('更新时间', auto_now=True)
|
|
|
|
class Meta:
|
|
ordering = ['-priority', 'created_at']
|
|
verbose_name = '任务'
|
|
verbose_name_plural = '任务'
|
|
|
|
def __str__(self):
|
|
return f"{self.title} ({self.get_status_display()})"
|
|
|
|
def mark_completed(self):
|
|
"""标记任务为已完成"""
|
|
self.status = 'completed'
|
|
self.progress_percent = 100
|
|
self.completed_at = timezone.now()
|
|
self.save()
|
|
|
|
def update_progress(self, percent, notes=''):
|
|
"""更新任务进展"""
|
|
self.progress_percent = percent
|
|
if percent > 0 and self.status == 'pending':
|
|
self.status = 'in_progress'
|
|
if percent == 100:
|
|
self.mark_completed()
|
|
if notes:
|
|
self.progress_notes = f"[{timezone.now().strftime('%Y-%m-%d %H:%M')}] {notes}\n" + self.progress_notes
|
|
self.save()
|