Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 67 additions & 2 deletions apps/web/src/components/HomeworkEditDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@
@keyup="updateCurrentLine"
/>

<div v-if="showPasteButtons" class="d-flex gap-2 justify-center">
<v-btn
size="small"
variant="outlined"
prepend-icon="mdi-content-paste"
@click="pasteFromClipboard"
>
粘贴
</v-btn>
<v-btn
size="small"
variant="elevated"
color="primary"
prepend-icon="mdi-content-paste"
@click="pasteAndComplete"
>
粘贴并完成
</v-btn>
</div>

<!-- Template Buttons Section -->
<div v-if="templateData" class="mt-4">
<div v-if="hasTemplates" class="template-buttons">
Expand Down Expand Up @@ -318,6 +338,9 @@ export default {
showQuickTools() {
return getSetting('display.showQuickTools')
},
showPasteButtons() {
return getSetting('display.showPasteButtons')
},
autoSavePromptText() {
return getSetting('edit.autoSavePromptText')
},
Expand All @@ -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')
Expand Down Expand Up @@ -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)
}
},
},
}
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
<v-divider class="my-2" />
<setting-item :setting-key="'display.showQuickTools'" />

<v-divider class="my-2" />
<setting-item :setting-key="'display.showPasteButtons'" />

<v-divider class="my-2" />
<setting-item :setting-key="'display.showAntiScreenBurnCard'" />

Expand Down
7 changes: 7 additions & 0 deletions apps/web/src/utils/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading