mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: AI dialog box, left mouse button menu (#2005)
This commit is contained in:
parent
2a63cd6bea
commit
de85895ad6
|
|
@ -47,7 +47,8 @@
|
|||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-router": "^4.2.4"
|
||||
"vue-router": "^4.2.4",
|
||||
"vue3-menus": "^1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.3.2",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<img v-if="application.avatar" :src="application.avatar" height="32px" width="32px" />
|
||||
<LogoIcon v-else height="32px" width="32px" />
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content" @click.stop @mouseup="openControl">
|
||||
<el-card shadow="always" class="dialog-card mb-8">
|
||||
<MdRenderer
|
||||
v-if="
|
||||
|
|
@ -56,6 +56,7 @@ import MdRenderer from '@/components/markdown/MdRenderer.vue'
|
|||
import OperationButton from '@/components/ai-chat/component/operation-button/index.vue'
|
||||
import { type chatType } from '@/api/type/application'
|
||||
import { computed } from 'vue'
|
||||
import bus from '@/bus'
|
||||
const props = defineProps<{
|
||||
chatRecord: chatType
|
||||
application: any
|
||||
|
|
@ -79,6 +80,13 @@ const chatMessage = (question: string, type: 'old' | 'new', other_params_data?:
|
|||
const add_answer_text_list = (answer_text_list: Array<any>) => {
|
||||
answer_text_list.push({ content: '' })
|
||||
}
|
||||
|
||||
const openControl = (event: any) => {
|
||||
if (props.type !== 'log') {
|
||||
bus.emit('open-control', event)
|
||||
}
|
||||
}
|
||||
|
||||
const answer_text_list = computed(() => {
|
||||
return props.chatRecord.answer_text_list.map((item) => {
|
||||
if (typeof item == 'string') {
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ import { MsgAlert } from '@/utils/message'
|
|||
import { type chatType } from '@/api/type/application'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getImgUrl } from '@/utils/utils'
|
||||
import bus from '@/bus'
|
||||
import 'recorder-core/src/engine/mp3'
|
||||
|
||||
import 'recorder-core/src/engine/mp3-engine'
|
||||
|
|
@ -542,6 +543,9 @@ function mouseleave() {
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
bus.on('chat-input', (message: string) => {
|
||||
inputValue.value = message
|
||||
})
|
||||
if (question) {
|
||||
inputValue.value = decodeURIComponent(question.trim())
|
||||
sendChatHandle()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
<template>
|
||||
<div>
|
||||
<vue3-menus v-model:open="isOpen" :event="eventVal" :menus="menus" hasIcon>
|
||||
<template #icon="{ menu }"
|
||||
><AppIcon v-if="menu.icon" :iconName="menu.icon"></AppIcon
|
||||
></template>
|
||||
<template #label="{ menu }"> {{ menu.label }}</template>
|
||||
</vue3-menus>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { Vue3Menus } from 'vue3-menus'
|
||||
import { MsgSuccess } from '@/utils/message'
|
||||
import AppIcon from '@/components/icons/AppIcon.vue'
|
||||
import bus from '@/bus'
|
||||
import { ref, nextTick, onMounted } from 'vue'
|
||||
const isOpen = ref<boolean>(false)
|
||||
const eventVal = ref({})
|
||||
function getSelection() {
|
||||
const selection = window.getSelection()
|
||||
if (selection && selection.anchorNode == null) {
|
||||
return null
|
||||
}
|
||||
const text = selection?.anchorNode?.textContent
|
||||
return text && text.substring(selection.anchorOffset, selection.focusOffset)
|
||||
}
|
||||
/**
|
||||
* 打开控制台
|
||||
* @param event
|
||||
*/
|
||||
const openControl = (event: any) => {
|
||||
const c = getSelection()
|
||||
isOpen.value = false
|
||||
if (c) {
|
||||
nextTick(() => {
|
||||
eventVal.value = event
|
||||
isOpen.value = true
|
||||
})
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
const menus = ref([
|
||||
{
|
||||
label: '复制',
|
||||
icon: 'app-copy',
|
||||
click: () => {
|
||||
const selectionText = getSelection()
|
||||
if (selectionText) {
|
||||
clearSelectedText()
|
||||
navigator.clipboard.writeText(selectionText).then(() => {
|
||||
MsgSuccess('复制成功')
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '引用',
|
||||
icon: 'app-quote',
|
||||
click: () => {
|
||||
bus.emit('chat-input', getSelection())
|
||||
clearSelectedText()
|
||||
}
|
||||
}
|
||||
])
|
||||
/**
|
||||
* 清除选中文本
|
||||
*/
|
||||
const clearSelectedText = () => {
|
||||
if (window.getSelection) {
|
||||
var selection = window.getSelection()
|
||||
if (selection) {
|
||||
selection.removeAllRanges()
|
||||
}
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
bus.on('open-control', openControl)
|
||||
})
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
|
|
@ -46,6 +46,7 @@
|
|||
>
|
||||
<template #operateBefore> <slot name="operateBefore" /> </template>
|
||||
</ChatInputOperate>
|
||||
<Control></Control>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
|
@ -63,6 +64,7 @@ import QuestionContent from '@/components/ai-chat/component/question-content/ind
|
|||
import ChatInputOperate from '@/components/ai-chat/component/chat-input-operate/index.vue'
|
||||
import PrologueContent from '@/components/ai-chat/component/prologue-content/index.vue'
|
||||
import UserForm from '@/components/ai-chat/component/user-form/index.vue'
|
||||
import Control from '@/components/ai-chat/component/control/index.vue'
|
||||
defineOptions({ name: 'AiChat' })
|
||||
const route = useRoute()
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -1374,4 +1374,25 @@ export const iconMap: any = {
|
|||
])
|
||||
}
|
||||
},
|
||||
'app-quote': {
|
||||
iconReader: () => {
|
||||
return h('i', [
|
||||
h(
|
||||
'svg',
|
||||
{
|
||||
style: { height: '100%', width: '100%' },
|
||||
viewBox: '0 0 1024 1024',
|
||||
version: '1.1',
|
||||
xmlns: 'http://www.w3.org/2000/svg'
|
||||
},
|
||||
[
|
||||
h('path', {
|
||||
d: 'M800.768 477.184c-14.336 0-30.72 2.048-45.056 4.096 18.432-51.2 77.824-188.416 237.568-315.392 36.864-28.672-20.48-86.016-59.392-57.344-155.648 116.736-356.352 317.44-356.352 573.44v20.48c0 122.88 100.352 223.232 223.232 223.232S1024 825.344 1024 702.464c0-124.928-100.352-225.28-223.232-225.28zM223.232 477.184c-14.336 0-30.72 2.048-45.056 4.096 18.432-51.2 77.824-188.416 237.568-315.392 36.864-28.672-20.48-86.016-59.392-57.344C200.704 225.28 0 425.984 0 681.984v20.48c0 122.88 100.352 223.232 223.232 223.232s223.232-100.352 223.232-223.232c0-124.928-100.352-225.28-223.232-225.28z',
|
||||
fill: 'currentColor'
|
||||
})
|
||||
]
|
||||
)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue