mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
refactor: simplify ChatGPT component state management
This commit is contained in:
parent
9e66c355bf
commit
4f674ec13e
1 changed files with 33 additions and 40 deletions
|
@ -1,6 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ChatComplicationMessage } from '@/api/openai'
|
import type { ChatComplicationMessage } from '@/api/openai'
|
||||||
import type { Ref } from 'vue'
|
|
||||||
import openai from '@/api/openai'
|
import openai from '@/api/openai'
|
||||||
import ChatGPT_logo from '@/assets/svg/ChatGPT_logo.svg?component'
|
import ChatGPT_logo from '@/assets/svg/ChatGPT_logo.svg?component'
|
||||||
import { urlJoin } from '@/lib/helper'
|
import { urlJoin } from '@/lib/helper'
|
||||||
|
@ -8,8 +7,8 @@ import { useSettingsStore, useUserStore } from '@/pinia'
|
||||||
import Icon, { SendOutlined } from '@ant-design/icons-vue'
|
import Icon, { SendOutlined } from '@ant-design/icons-vue'
|
||||||
import hljs from 'highlight.js'
|
import hljs from 'highlight.js'
|
||||||
import nginx from 'highlight.js/lib/languages/nginx'
|
import nginx from 'highlight.js/lib/languages/nginx'
|
||||||
import { Marked } from 'marked'
|
|
||||||
|
|
||||||
|
import { Marked } from 'marked'
|
||||||
import { markedHighlight } from 'marked-highlight'
|
import { markedHighlight } from 'marked-highlight'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import 'highlight.js/styles/vs2015.css'
|
import 'highlight.js/styles/vs2015.css'
|
||||||
|
@ -17,28 +16,19 @@ import 'highlight.js/styles/vs2015.css'
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
content: string
|
content: string
|
||||||
path?: string
|
path?: string
|
||||||
historyMessages?: ChatComplicationMessage[]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits(['update:history_messages'])
|
|
||||||
|
|
||||||
hljs.registerLanguage('nginx', nginx)
|
hljs.registerLanguage('nginx', nginx)
|
||||||
|
|
||||||
const { language: current } = storeToRefs(useSettingsStore())
|
const { language: current } = storeToRefs(useSettingsStore())
|
||||||
|
|
||||||
const history_messages = computed(() => props.historyMessages)
|
const messages = defineModel<ChatComplicationMessage[]>('historyMessages', {
|
||||||
const messages = ref([]) as Ref<ChatComplicationMessage[] | undefined>
|
type: Array,
|
||||||
|
default: reactive([]),
|
||||||
onMounted(() => {
|
|
||||||
messages.value = props.historyMessages
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(history_messages, () => {
|
|
||||||
messages.value = props.historyMessages
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const ask_buffer = ref('')
|
const askBuffer = ref('')
|
||||||
|
|
||||||
async function request() {
|
async function request() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
@ -52,9 +42,11 @@ async function request() {
|
||||||
|
|
||||||
const { token } = storeToRefs(user)
|
const { token } = storeToRefs(user)
|
||||||
|
|
||||||
messages.value?.push(t.value)
|
messages.value = [...messages.value!, t.value]
|
||||||
|
|
||||||
emit('update:history_messages', messages.value)
|
await nextTick()
|
||||||
|
|
||||||
|
scrollToBottom()
|
||||||
|
|
||||||
const res = await fetch(urlJoin(window.location.pathname, '/api/chatgpt'), {
|
const res = await fetch(urlJoin(window.location.pathname, '/api/chatgpt'), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -76,7 +68,7 @@ async function request() {
|
||||||
scrollToBottom()
|
scrollToBottom()
|
||||||
}, 500)
|
}, 500)
|
||||||
loading.value = false
|
loading.value = false
|
||||||
store_record()
|
storeRecord()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
apply(value!)
|
apply(value!)
|
||||||
|
@ -146,18 +138,21 @@ async function send() {
|
||||||
messages.value = []
|
messages.value = []
|
||||||
|
|
||||||
if (messages.value.length === 0) {
|
if (messages.value.length === 0) {
|
||||||
messages.value.push({
|
messages.value = [{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: `${props.content}\n\nCurrent Language Code: ${current.value}`,
|
content: `${props.content}\n\nCurrent Language Code: ${current.value}`,
|
||||||
})
|
}]
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
messages.value.push({
|
messages.value = [...messages.value, {
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: ask_buffer.value,
|
content: askBuffer.value,
|
||||||
})
|
}]
|
||||||
ask_buffer.value = ''
|
askBuffer.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
await request()
|
await request()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,9 +162,7 @@ const marked = new Marked(
|
||||||
highlight(code, lang) {
|
highlight(code, lang) {
|
||||||
const language = hljs.getLanguage(lang) ? lang : 'nginx'
|
const language = hljs.getLanguage(lang) ? lang : 'nginx'
|
||||||
|
|
||||||
const highlightedCode = hljs.highlight(code, { language }).value
|
return hljs.highlight(code, { language }).value
|
||||||
|
|
||||||
return `<pre><code class="hljs ${language}">${highlightedCode}</code></pre>`
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
@ -180,27 +173,27 @@ marked.setOptions({
|
||||||
breaks: false,
|
breaks: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
function store_record() {
|
function storeRecord() {
|
||||||
openai.store_record({
|
openai.store_record({
|
||||||
file_name: props.path,
|
file_name: props.path,
|
||||||
messages: messages.value,
|
messages: messages.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear_record() {
|
function clearRecord() {
|
||||||
openai.store_record({
|
openai.store_record({
|
||||||
file_name: props.path,
|
file_name: props.path,
|
||||||
messages: [],
|
messages: [],
|
||||||
})
|
})
|
||||||
messages.value = []
|
messages.value = []
|
||||||
emit('update:history_messages', [])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const editing_idx = ref(-1)
|
const editingIdx = ref(-1)
|
||||||
|
|
||||||
async function regenerate(index: number) {
|
async function regenerate(index: number) {
|
||||||
editing_idx.value = -1
|
editingIdx.value = -1
|
||||||
messages.value = messages.value?.slice(0, index)
|
messages.value = messages.value?.slice(0, index)
|
||||||
|
await nextTick()
|
||||||
await request()
|
await request()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,27 +230,27 @@ const show = computed(() => !messages.value || messages.value?.length === 0)
|
||||||
<AComment :author="item.role === 'assistant' ? $gettext('Assistant') : $gettext('User')">
|
<AComment :author="item.role === 'assistant' ? $gettext('Assistant') : $gettext('User')">
|
||||||
<template #content>
|
<template #content>
|
||||||
<div
|
<div
|
||||||
v-if="item.role === 'assistant' || editing_idx !== index"
|
v-if="item.role === 'assistant' || editingIdx !== index"
|
||||||
v-dompurify-html="marked.parse(item.content)"
|
v-dompurify-html="marked.parse(item.content)"
|
||||||
class="content"
|
class="content"
|
||||||
/>
|
/>
|
||||||
<AInput
|
<AInput
|
||||||
v-else
|
v-else
|
||||||
v-model:value="item.content"
|
v-model:value="item.content"
|
||||||
style="padding: 0"
|
class="pa-0"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<span
|
<span
|
||||||
v-if="item.role === 'user' && editing_idx !== index"
|
v-if="item.role === 'user' && editingIdx !== index"
|
||||||
@click="editing_idx = index"
|
@click="editingIdx = index"
|
||||||
>
|
>
|
||||||
{{ $gettext('Modify') }}
|
{{ $gettext('Modify') }}
|
||||||
</span>
|
</span>
|
||||||
<template v-else-if="editing_idx === index">
|
<template v-else-if="editingIdx === index">
|
||||||
<span @click="regenerate(index + 1)">{{ $gettext('Save') }}</span>
|
<span @click="regenerate(index + 1)">{{ $gettext('Save') }}</span>
|
||||||
<span @click="editing_idx = -1">{{ $gettext('Cancel') }}</span>
|
<span @click="editingIdx = -1">{{ $gettext('Cancel') }}</span>
|
||||||
</template>
|
</template>
|
||||||
<span
|
<span
|
||||||
v-else-if="!loading"
|
v-else-if="!loading"
|
||||||
|
@ -277,7 +270,7 @@ const show = computed(() => !messages.value || messages.value?.length === 0)
|
||||||
:cancel-text="$gettext('No')"
|
:cancel-text="$gettext('No')"
|
||||||
:ok-text="$gettext('OK')"
|
:ok-text="$gettext('OK')"
|
||||||
:title="$gettext('Are you sure you want to clear the record of chat?')"
|
:title="$gettext('Are you sure you want to clear the record of chat?')"
|
||||||
@confirm="clear_record"
|
@confirm="clearRecord"
|
||||||
>
|
>
|
||||||
<AButton type="text">
|
<AButton type="text">
|
||||||
{{ $gettext('Clear') }}
|
{{ $gettext('Clear') }}
|
||||||
|
@ -292,7 +285,7 @@ const show = computed(() => !messages.value || messages.value?.length === 0)
|
||||||
</ASpace>
|
</ASpace>
|
||||||
</div>
|
</div>
|
||||||
<ATextarea
|
<ATextarea
|
||||||
v-model:value="ask_buffer"
|
v-model:value="askBuffer"
|
||||||
auto-size
|
auto-size
|
||||||
/>
|
/>
|
||||||
<div class="send-btn">
|
<div class="send-btn">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue