diff --git a/apps/web/src/components/HomeworkEditDialog.vue b/apps/web/src/components/HomeworkEditDialog.vue
index ba5fc677..ad3040ae 100644
--- a/apps/web/src/components/HomeworkEditDialog.vue
+++ b/apps/web/src/components/HomeworkEditDialog.vue
@@ -30,6 +30,26 @@
@keyup="updateCurrentLine"
/>
+
@@ -318,6 +338,9 @@ export default {
showQuickTools() {
return getSetting('display.showQuickTools')
},
+ showPasteButtons() {
+ return getSetting('display.showPasteButtons')
+ },
autoSavePromptText() {
return getSetting('edit.autoSavePromptText')
},
@@ -328,8 +351,9 @@ export default {
watch: {
async modelValue(newValue) {
if (newValue) {
- // 当对话框打开时,重置内容为初始内容
- this.content = this.initialContent
+ // 当对话框打开时,重置内容为初始内容;最后一行不是空行时,在文末加一个空行
+ const initial = this.initialContent || ''
+ this.content = initial === '' || initial.endsWith('\n') ? initial : initial + '\n'
// 加载模板数据
try {
this.templateData = await dataProvider.loadData('classworks-config-homework-template')
@@ -526,6 +550,47 @@ export default {
})
}
},
+ // 从剪贴板读取内容并按光标位置组装新正文:有选中则替换,否则在光标处插入
+ // 剪贴板完全为空时返回 null,空格或换行视为有效内容原样粘贴
+ async buildContentWithPaste() {
+ const text = await navigator.clipboard.readText()
+ if (text == null || text === '') return null
+ const textarea = this.$refs.inputRef.$el.querySelector('textarea')
+ const start = textarea.selectionStart
+ const end = textarea.selectionEnd
+ return {
+ content: this.content.slice(0, start) + text + this.content.slice(end),
+ cursorPosition: start + text.length,
+ }
+ },
+ // 从剪贴板粘贴,保留在对话框继续编辑
+ async pasteFromClipboard() {
+ try {
+ const result = await this.buildContentWithPaste()
+ if (!result) return
+ this.content = result.content
+ this.$nextTick(() => {
+ const textarea = this.$refs.inputRef.$el.querySelector('textarea')
+ textarea.focus()
+ textarea.setSelectionRange(result.cursorPosition, result.cursorPosition)
+ this.updateCurrentLine()
+ })
+ } catch (error) {
+ console.error('Failed to read clipboard:', error)
+ }
+ },
+ // 从剪贴板粘贴并直接保存关闭,插入逻辑与粘贴一致
+ async pasteAndComplete() {
+ try {
+ const result = await this.buildContentWithPaste()
+ if (!result) return
+ this.content = result.content
+ this.$emit('save', this.content.trim())
+ this.dialogVisible = false
+ } catch (error) {
+ console.error('Failed to read clipboard:', error)
+ }
+ },
},
}
diff --git a/apps/web/src/components/settings/cards/DisplaySettingsCard.vue b/apps/web/src/components/settings/cards/DisplaySettingsCard.vue
index 6f1618fa..91724cb3 100644
--- a/apps/web/src/components/settings/cards/DisplaySettingsCard.vue
+++ b/apps/web/src/components/settings/cards/DisplaySettingsCard.vue
@@ -45,6 +45,9 @@
+
+
+
diff --git a/apps/web/src/utils/settings.js b/apps/web/src/utils/settings.js
index 53b539f4..ae136734 100644
--- a/apps/web/src/utils/settings.js
+++ b/apps/web/src/utils/settings.js
@@ -212,6 +212,13 @@ const settingsDefinitions = {
description: '是否显示快捷键盘',
icon: 'mdi-dialpad',
},
+ 'display.showPasteButtons': {
+ type: 'boolean',
+ default: true,
+ description: '是否显示作业编辑粘贴按钮',
+ icon: 'mdi-content-paste',
+ // 控制作业编辑对话框中的「粘贴」与「粘贴并完成」按钮,关闭后仅保留手动编辑
+ },
'display.forceDesktopMode': {
type: 'boolean',
default: false,