Version: 0.9.39.dev.260423

后端:
1. 记忆系统移除 todo_hint 类型——随口记已由 Task 系统承接,todo_hint 语义重叠且无完成追踪
- 全链路清理:常量、校验、默认重要度、30 天 TTL、读取预算、LLM 抽取提示词枚举
- 总预算从四类收缩为三类(preference / constraint / fact)

2. 记忆抽取触发点从 chat-persist 移至 graph-completion——避免随口记消息被误提取为 constraint/preference
- chat-persist consumer 不再自动入队 memory.extract.requested,仅负责聊天历史落库
- graph 完成后新增条件发布:检测 UsedQuickNote 标记,调用过 quick_note_create 则跳过记忆抽取
- ResetForNextRun 重置 UsedQuickNote,防止跨轮残留导致后续正常消息记忆抽取被误跳过

3. 任务类查询接口返回 items 补充数据库主键 ID(前端拖拽编排依赖此字段)

前端:
4. 排程视图新增手动编排模式——侧边栏任务块拖拽入周课表 + 悬浮删除热区 + 建议块虚线标识
- TaskClassSidebar 拖拽发起 + 预览态嵌入时间格式化(含周次/星期)
- WeekPlanningBoard 外部拖入 / 内部移动 / 悬浮删除区交互
- ScheduleView 手动编排状态机(进入/退出/取消/覆盖确认)+ apply 时同步处理新增与删除
This commit is contained in:
Losita
2026-04-23 23:07:04 +08:00
parent 53e2602df4
commit ba8e8e2a82
23 changed files with 640 additions and 154 deletions

View File

@@ -11,6 +11,7 @@ const props = defineProps<{
expandedTaskClassDetail: TaskClassDetail | null
selectedTaskClassIds: number[]
taskClassMultiSelectMode: boolean
manualEditMode: boolean
}>()
const emit = defineEmits<{
@@ -35,14 +36,45 @@ function isSelected(taskClassId: number) {
}
function formatEmbeddedTime(value: TaskClassDetail['items'][number]['embedded_time']) {
if (!value?.date) {
if (!value && !(value as any)?._preview_week) {
return '未安排'
}
const weekDays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
const weekNum = (value as any)?._preview_week
const dayNum = (value as any)?._day_of_week
if (weekNum && dayNum) {
return `${weekNum}${weekDays[dayNum - 1]} ${value?.section_from || 0}-${value?.section_to || 0}`
}
if (!value?.date) return '未安排'
const date = new Date(value.date)
// getDay() 返回 0 (周日) 到 6 (周六)。 转换成我们的 1-7。
const rawDay = date.getDay()
const displayDay = rawDay === 0 ? 6 : rawDay - 1 // 对应 weekDays 索引
const month = `${date.getMonth() + 1}`.padStart(2, '0')
const day = `${date.getDate()}`.padStart(2, '0')
return `${month}.${day} ${value.section_from}-${value.section_to}`
return `${month}.${day} ${weekDays[displayDay]} ${value.section_from}-${value.section_to}`
}
function handleDragStart(item: TaskClassDetail['items'][number], dragEvent: DragEvent) {
if (!props.manualEditMode) return
dragEvent.dataTransfer?.setData(
'application/task-item',
JSON.stringify({
id: item.id,
content: item.content,
taskClassId: props.expandedTaskClassId,
}),
)
if (dragEvent.dataTransfer) {
dragEvent.dataTransfer.effectAllowed = 'move'
}
}
function syncViewportHeight() {
@@ -181,6 +213,9 @@ watch(
v-for="item in expandedTaskClassDetail.items"
:key="item.order"
class="task-class-card__detail-item"
:class="{ 'task-class-card__detail-item--draggable': manualEditMode }"
:draggable="manualEditMode"
@dragstart="handleDragStart(item, $event)"
>
<span class="task-class-card__detail-order">{{ item.order }}</span>
<span class="task-class-card__detail-text">{{ item.content }}</span>
@@ -471,6 +506,17 @@ watch(
align-items: center;
}
.task-class-card__detail-item--draggable {
cursor: grab;
transition: all 0.2s;
}
.task-class-card__detail-item--draggable:hover {
border-color: #3b82f6;
background: #f1f5f9;
transform: translateX(4px);
}
.task-class-card__detail-order {
color: #17253d;
font-weight: 700;