feat(流程图): 「写代码 / 画流程图」变成工具栏上的切换,AI 的评分和历次分数挪进结果页签,题单里也能画
- 流程图题的工具栏最左边是「写代码 / 画流程图」。原来流程图藏在语言下拉里,叫一个名叫 Flowchart 的「语言」;画完一道题之后它还被记成语言偏好,下一道能画的题一打开就是画布 - 「交给 AI 点评」交完切到「结果」页签:评的时候写着「AI 正在看你的图」、画布照样能改; 评完是分数、评语、改进建议、四项得分,顶上一排历次分数,点哪次看哪次。 原来是提交按钮旁一个 1000px 的弹框,盖住画布,翻历次评分要一页一页点 - 画到 A / S:给「照着它写代码 →」,题单里 1.5 秒后回题单(和代码通过一样), 课堂条当场标成做完;只在这一页上刚评完的那次才算,进页面读到以前的 A 不跳 - 「把这一版载回画布」只在画布和那一版不一样时出现;载回、进页面读回草稿后都缩放到装下整张图 - 题单入口能画流程图了(原来只有题库入口能画),题单里的代码草稿、流程图草稿各存一份, 加入题单之前写的、画的不会一进题单就摆在编辑器里 - 手机上不给「画流程图」(节点库是拖放,手机上拖不动),题面里以前画好的那张照样看得到 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3fe3caa944
commit
11368813cc
16 files changed
+747
-388
No files matched your search
@@ -24,7 +24,22 @@ interface Props {
|
||||
const { height = "calc(100vh - 133px)" } = defineProps<Props>()
|
||||
|
||||
// Vue Flow 实例
|
||||
const { addEdges, removeNodes, removeEdges } = useVueFlow()
|
||||
const { addEdges, removeNodes, removeEdges, fitView, onNodesInitialized } = useVueFlow()
|
||||
|
||||
/**
|
||||
* 进页面读回草稿、载回旧版之后缩放到正好装下整张图。原来画布停在默认的位置和缩放上,
|
||||
* 图大一点就有一半在外面,学生以为草稿丢了。只在这两种时候缩:拖进一个新节点时也会
|
||||
* 触发 nodes-initialized,那时候跟着缩放会让画布跳一下
|
||||
*/
|
||||
let fitPending = false
|
||||
function fitSoon() {
|
||||
fitPending = true
|
||||
}
|
||||
onNodesInitialized(() => {
|
||||
if (!fitPending) return
|
||||
fitPending = false
|
||||
fitView({ padding: 0.15, maxZoom: 1.2 })
|
||||
})
|
||||
|
||||
// 节点和边的响应式数据
|
||||
// 显式标注成 Ref<Node[]>,不走 ref<T>() 的 UnwrapRef 推导 —— vue-flow 的
|
||||
@@ -37,12 +52,18 @@ const { canUndo, canRedo, resetHistory, saveState, undo, redo } = useHistory()
|
||||
|
||||
const problemStore = useProblemStore()
|
||||
const { problem } = storeToRefs(problemStore)
|
||||
// 缓存管理:用 computed key 支持题目 ID 异步加载后自动切换到正确的 storage
|
||||
const cacheKey = computed(() =>
|
||||
problem.value?._id
|
||||
? `flowchart-editor-data-problem-${problem.value!._id}`
|
||||
: "flowchart-editor-data",
|
||||
)
|
||||
const route = useRoute()
|
||||
/**
|
||||
* 缓存管理:用 computed key 支持题目 ID 异步加载后自动切换到正确的 storage。
|
||||
* 题单入口单独一份草稿:加入题单之前在题库里画到 A 的那张,不能一进题单就摆在画布上
|
||||
* (设计文档第 11 节 3,和代码草稿同理)
|
||||
*/
|
||||
const cacheKey = computed(() => {
|
||||
if (!problem.value?._id) return "flowchart-editor-data"
|
||||
const base = `flowchart-editor-data-problem-${problem.value._id}`
|
||||
const problemSetId = route.params.problemSetId
|
||||
return problemSetId ? `${base}-problemset-${problemSetId}` : base
|
||||
})
|
||||
const { isSaving, lastSaved, hasUnsavedChanges, saveToCache, loadFromCache, clearCache } = useCache(
|
||||
nodes,
|
||||
edges,
|
||||
@@ -51,6 +72,7 @@ const { isSaving, lastSaved, hasUnsavedChanges, saveToCache, loadFromCache, clea
|
||||
// 换题后画布已经被换成新题的草稿,历史必须跟着重建,
|
||||
// 否则一次撤销就会把上一题的图还原到这一题里
|
||||
resetHistory(nodes.value, edges.value)
|
||||
fitSoon()
|
||||
},
|
||||
)
|
||||
|
||||
@@ -152,6 +174,7 @@ onMounted(() => {
|
||||
// 否则第一步操作没有可回退的目标,撤销按钮一直是灰的
|
||||
loadFromCache()
|
||||
resetHistory(nodes.value, edges.value)
|
||||
fitSoon()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
@@ -177,6 +200,7 @@ const setFlowchartData = (data: { nodes: Node[]; edges: Edge[] }) => {
|
||||
nodes.value = processedNodes
|
||||
edges.value = processedEdges
|
||||
saveState(nodes.value, edges.value)
|
||||
fitSoon()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user