WIP-CHECKPOINT[auth-refactor]: 固化工程师崩溃前部分成果 + 同树其他未提交WIP(仅源码,不含密钥/二进制)-- 待重激活工程师续作
This commit is contained in:
@@ -51,31 +51,17 @@
|
||||
<!-- 点击表情面板外部关闭 -->
|
||||
<div v-if="showEmojiPicker" class="emoji-picker-overlay" @click="showEmojiPicker = false"></div>
|
||||
</div>
|
||||
<button class="tb-btn" title="图片" @click="handleToolbarClick('image')">
|
||||
🖼
|
||||
<span class="tb-tip">图片</span>
|
||||
</button>
|
||||
<button class="tb-btn" title="截图" @click="handleToolbarClick('screenshot')">
|
||||
✂
|
||||
<span class="tb-tip">截图</span>
|
||||
</button>
|
||||
|
||||
<button class="tb-btn" title="文件" @click="handleToolbarClick('file')">
|
||||
📎
|
||||
<span class="tb-tip">文件</span>
|
||||
</button>
|
||||
<button class="tb-btn" title="语音" @click="handleToolbarClick('voice')">
|
||||
🎤
|
||||
<span class="tb-tip">语音</span>
|
||||
</button>
|
||||
|
||||
<div class="tb-sep"></div>
|
||||
<button class="tb-btn" title="邀请员工/部门" @click="showInviteDialog = true">
|
||||
👥
|
||||
<span class="tb-tip">邀请</span>
|
||||
</button>
|
||||
<button class="tb-btn" title="远程协助" @click="handleToolbarClick('remote')">
|
||||
🖥
|
||||
<span class="tb-tip">远程协助</span>
|
||||
</button>
|
||||
<button class="tb-btn" title="快速回复" @click="handleToolbarClick('quickReply')">
|
||||
⚡
|
||||
<span class="tb-tip">快速回复</span>
|
||||
@@ -125,6 +111,13 @@
|
||||
@confirm="onScreenshotConfirm"
|
||||
@cancel="onScreenshotCancel"
|
||||
/>
|
||||
|
||||
<!-- 框选截图模式 -->
|
||||
<ScreenCapture
|
||||
v-if="showScreenCapture"
|
||||
@confirm="onBoxCaptureConfirm"
|
||||
@cancel="onBoxCaptureCancel"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -138,6 +131,7 @@ import html2canvas from 'html2canvas-pro'
|
||||
import { useConversationStore } from '@/stores/conversation'
|
||||
import InviteParticipantDialog from '@/components/conversation/InviteParticipantDialog.vue'
|
||||
import ScreenshotEditor from './ScreenshotEditor.vue'
|
||||
import ScreenCapture from './ScreenCapture.vue'
|
||||
import { uploadFile } from '@/api/upload'
|
||||
import { sendMessage } from '@/api/message'
|
||||
import type { Message } from '@/api/message'
|
||||
@@ -221,6 +215,9 @@ const showInviteDialog = ref(false)
|
||||
/** 截图编辑器是否可见 */
|
||||
const showScreenshotEditor = ref(false)
|
||||
|
||||
/** 框选截图模式是否可见 */
|
||||
const showScreenCapture = ref(false)
|
||||
|
||||
/** html2canvas 生成的完整页面截图 Canvas 对象(传给 ScreenshotEditor) */
|
||||
let screenshotCanvas: HTMLCanvasElement | null = null
|
||||
const showEmojiPicker = ref(false)
|
||||
@@ -668,6 +665,104 @@ async function handleScreenshot(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 框选截图 - 直接在屏幕上框选区域
|
||||
*/
|
||||
function startBoxCapture(): void {
|
||||
const convId = conversationStore.currentConversation?.id
|
||||
if (!convId) {
|
||||
ElMessage.warning('请先选择一个会话')
|
||||
return
|
||||
}
|
||||
showScreenCapture.value = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 框选截图确认
|
||||
*/
|
||||
async function onBoxCaptureConfirm(blob: Blob): Promise<void> {
|
||||
showScreenCapture.value = false
|
||||
const convId = conversationStore.currentConversation?.id
|
||||
if (!convId) return
|
||||
|
||||
try {
|
||||
ElMessage.info('截图上传中...')
|
||||
const result = await uploadFile(blob)
|
||||
const newMsg = await sendMessage(convId, '[截图]', 'image', {
|
||||
media_url: result.url,
|
||||
file_name: result.filename,
|
||||
file_size: result.file_size,
|
||||
})
|
||||
conversationStore.messages.push(newMsg)
|
||||
ElMessage.success('截图发送成功')
|
||||
} catch (error: any) {
|
||||
console.error('[ReplyBox] 框选截图发送失败:', error)
|
||||
ElMessage.error(`截图发送失败:${error?.message || '未知错误'}`)
|
||||
}
|
||||
}
|
||||
|
||||
function onBoxCaptureCancel(): void {
|
||||
showScreenCapture.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 跨屏截图 - 使用系统屏幕捕获API
|
||||
*/
|
||||
async function handleScreenCapture(): Promise<void> {
|
||||
const convId = conversationStore.currentConversation?.id
|
||||
if (!convId) {
|
||||
ElMessage.warning('请先选择一个会话')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
ElMessage.info('选择要截取的屏幕...')
|
||||
|
||||
// 使用系统屏幕捕获API
|
||||
const stream = await navigator.mediaDevices.getDisplayMedia({
|
||||
video: {
|
||||
displaySurface: 'monitor', // 优先捕获整个屏幕
|
||||
},
|
||||
audio: false,
|
||||
})
|
||||
|
||||
// 获取视频轨道
|
||||
const videoTrack = stream.getVideoTracks()[0]
|
||||
const settings = videoTrack.getSettings()
|
||||
|
||||
// 创建视频元素来捕获帧
|
||||
const video = document.createElement('video')
|
||||
video.srcObject = new MediaStream([videoTrack])
|
||||
await video.play()
|
||||
|
||||
// 创建 canvas 捕获帧
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = settings.width || video.videoWidth
|
||||
canvas.height = settings.height || video.videoHeight
|
||||
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (ctx) {
|
||||
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
|
||||
}
|
||||
|
||||
// 停止屏幕共享
|
||||
videoTrack.stop()
|
||||
stream.getTracks().forEach(track => track.stop())
|
||||
|
||||
// 转换为图片
|
||||
screenshotCanvas = canvas
|
||||
showScreenshotEditor.value = true
|
||||
ElMessage.success('截取成功')
|
||||
} catch (error: any) {
|
||||
if (error.name === 'NotAllowedError') {
|
||||
ElMessage.info('已取消跨屏截图')
|
||||
} else {
|
||||
console.error('跨屏截图失败:', error)
|
||||
ElMessage.error('跨屏截图失败,请重试')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认发送截图
|
||||
* 上传截图并发送图片消息
|
||||
|
||||
Reference in New Issue
Block a user