Commit 39905505 authored by nick zheng's avatar nick zheng

chore: 没有应用名称时不可发布及补充优化角色指令

parent e1a430eb
......@@ -9,6 +9,9 @@ interface Props {
width?: number // 宽度
borderRadius?: number // 圆角
btnLoading?: boolean // 按钮是否加载中
btnDisabled?: boolean // 按钮是否禁用
cancelBtnText?: string // 取消按钮文字
confirmBtnText?: string // 取消按钮文字
labelWidth?: number // 标签的宽度
labelPlacement?: 'left' | 'top' // 标签显示的位置
}
......@@ -23,6 +26,10 @@ const props = withDefaults(defineProps<Props>(), {
height: 240,
width: 500,
borderRadius: 6,
btnLoading: false,
btnDisabled: false,
cancelBtnText: '取 消',
confirmBtnText: '确认',
labelWidth: 80,
labelPlacement: 'left',
})
......@@ -79,14 +86,15 @@ function handleDetele() {
<template #footer>
<div class="flex w-full items-center justify-end">
<NButton class="h-[32px]! w-[80px]! rounded-md!" @click="handleCloseModal"> 取 消 </NButton>
<NButton class="h-[32px]! rounded-md! px-6!" @click="handleCloseModal"> {{ cancelBtnText }} </NButton>
<NButton
:loading="btnLoading"
type="primary"
class="h-[32px]! w-[80px]! rounded-md! ml-4!"
:disabled="btnDisabled"
class="h-[32px]! px-6! rounded-md! ml-4!"
@click="handleDetele"
>
确 定
{{ confirmBtnText }}
</NButton>
</div>
</template>
......
<script setup lang="ts">
import { computed, ref, watchEffect } from 'vue'
import CustomModal from '@/components/custom-modal/custom-modal.vue'
interface Props {
modalTitle: string
isShowModal: boolean
btnLoading: boolean
questionSystem: string
}
interface Emits {
(e: 'update:isShowModal', value: boolean): void
(e: 'comfirm', value: string): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const continuousQuestionSystem = ref('')
watchEffect(() => {
continuousQuestionSystem.value = props.questionSystem
})
const showModal = computed({
get() {
return props.isShowModal
},
set(value: boolean) {
emit('update:isShowModal', value)
},
})
function handleAdditionalPrompt() {
emit('comfirm', continuousQuestionSystem.value)
}
</script>
<template>
<CustomModal
v-model:is-show="showModal"
:title="modalTitle"
:btn-loading="btnLoading"
:height="636"
:width="520"
@confirm="handleAdditionalPrompt"
>
<template #content>
<p class="mb-3 select-none text-[#84868c]">可在追问prompt中指引追问的字数、风格和内容范围。</p>
<NInput
v-model:value="continuousQuestionSystem"
type="textarea"
:rows="19"
maxlength="1000"
show-count
placeholder="请输入追问prompt"
class="rounded-lg!"
/>
</template>
</CustomModal>
</template>
<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { SelectOption, UploadFileInfo } from 'naive-ui'
import { FormInst, SelectOption, UploadFileInfo } from 'naive-ui'
import { useThrottleFn } from '@vueuse/core'
import CustomIcon from '@/components/custom-icon/custom-icon.vue'
import UploadPhoto from '@/components/upload-photo/upload-photo.vue'
import OptimizeSystemModal from './optimize-system-modal.vue'
import { usePersonalAppConfigStore } from '@/store/modules/personal-app-config'
import { PersonalAppConfigState } from '@/store/types/personal-app-config'
import {
......@@ -51,10 +52,20 @@ const commConfigExpandedNames = ref<string[]>(['continuousQuestion'])
const isInitGetAgentAppDetail = ref(false)
const isShowOptimizeAgentSystemModal = ref(false) // 是否显示优化角色指令对话框
const generateAgentAvatarLoading = ref(false) // 是否正在生成图片
const generatePreambleLoading = ref(false) // 是否正在生成开场白
const generateFeaturedQuestionsLoading = ref(false) // 是否正在生成推荐词
const personalAppFormRef = ref<FormInst | null>(null)
const personalAppRules = {
baseInfo: {
agentTitle: [{ required: true, message: '请输入应用名称', trigger: 'blur' }],
},
}
const personalAppConfig = computed(() => {
return personalAppConfigStore.$state
})
......@@ -108,6 +119,11 @@ async function handleGetAgentApplicationDetail(agentId: string) {
res.data.baseInfo.agentAvatar || 'https://gsst-poe-sit.gz.bcebos.com/data/20240911/1726041369632.webp',
},
})
;['preamble', 'featuredQuestions']
.filter((property) => personalAppConfig.value.commConfig[property as keyof PersonalAppConfigState['commConfig']])
.forEach((property) => {
commConfigExpandedNames.value.push(property)
})
}
}
......@@ -139,6 +155,12 @@ async function handleUpdatePersonalAppId() {
}
}
function handleShowOptimizeAgentSystemModal() {
if (!personalAppConfig.value.baseInfo.agentSystem) return
isShowOptimizeAgentSystemModal.value = true
}
function handleSettingDefaultPrompt() {
personalAppConfig.value.baseInfo.agentSystem = defaultPrompt
}
......@@ -173,13 +195,19 @@ async function handleAIGeneratePreamble() {
generatePreambleLoading.value = true
const res = await fetchCreatePreamble({
const res = await fetchCreatePreamble<string>({
agentTitle: personalAppConfig.value.baseInfo.agentTitle,
agentDesc: personalAppConfig.value.baseInfo.agentDesc,
}).finally(() => (generatePreambleLoading.value = false))
if (res.code === 0) {
personalAppConfig.value.commConfig.preamble = res.data as string
try {
const content = res.data.replace(/^```json|```$/g, '')
const preamble = JSON.parse(content)['output']
personalAppConfig.value.commConfig.preamble = preamble
} catch (error) {
window.$message.error('生成内容格式出错啦')
}
}
}
......@@ -198,6 +226,11 @@ async function handleAIGenerateFeaturedQuestions() {
personalAppConfig.value.commConfig.featuredQuestions = res.data
}
}
function handleSettingAgentSystem(agentSystem: string) {
personalAppConfig.value.baseInfo.agentSystem = agentSystem
isShowOptimizeAgentSystemModal.value = false
}
</script>
<template>
......@@ -351,8 +384,14 @@ async function handleAIGenerateFeaturedQuestions() {
</div>
</div>
<div class="flex flex-1">
<NForm label-placement="left" class="flex-1">
<NFormItem feedback-style="height: 14px">
<NForm
ref="personalAppFormRef"
:model="personalAppConfig"
:rules="personalAppRules"
label-placement="left"
class="flex-1"
>
<NFormItem feedback-class="p-0.5! text-xs!" path="baseInfo.agentTitle">
<NInput
v-model:value="personalAppConfig.baseInfo.agentTitle"
:maxlength="50"
......@@ -396,18 +435,40 @@ async function handleAIGenerateFeaturedQuestions() {
</NPopover>
</div>
<NPopover style="width: 200px" content-style="padding: 10px 0;" trigger="hover">
<template #trigger>
<div
class="text-theme-color flex cursor-pointer items-center hover:opacity-80"
@click="handleSettingDefaultPrompt"
>
<CustomIcon icon="solar:book-2-broken" class="mr-3 text-base" />
<span class="text-xs">模板</span>
</div>
</template>
<p class="text-xs" style="white-space: pre-wrap">{{ defaultPrompt }}</p>
</NPopover>
<div class="flex items-center justify-center">
<NPopover trigger="hover">
<template #trigger>
<div
class="text-theme-color flex items-center border-r border-[#e8e9eb] pr-[9px]"
:class="
personalAppConfig.baseInfo.agentSystem
? 'cursor-pointer hover:opacity-80'
: 'cursor-not-allowed opacity-50'
"
@click="handleShowOptimizeAgentSystemModal"
>
<div
class="mr-3 mt-[-2px] h-[16px] w-[16px] bg-[url(@/assets/svgs/star.svg)] bg-[length:100%_100%]"
/>
<span class="text-xs">优化</span>
</div>
</template>
<p class="text-xs">AI优化</p>
</NPopover>
<NPopover style="width: 200px" content-style="padding: 10px 0;" trigger="hover">
<template #trigger>
<div
class="text-theme-color flex cursor-pointer items-center pl-[9px] hover:opacity-80"
@click="handleSettingDefaultPrompt"
>
<CustomIcon icon="solar:book-2-broken" class="mr-3 text-base" />
<span class="text-xs">模板</span>
</div>
</template>
<p class="text-xs" style="white-space: pre-wrap">{{ defaultPrompt }}</p>
</NPopover>
</div>
</div>
<div class="flex flex-1 p-1 pl-6">
......@@ -563,6 +624,13 @@ async function handleAIGenerateFeaturedQuestions() {
</div>
</div>
</div>
<OptimizeSystemModal
v-model:is-show-modal="isShowOptimizeAgentSystemModal"
:btn-loading="false"
modal-title="角色指令优化"
@comfirm="handleSettingAgentSystem"
/>
</template>
<style lang="scss" scoped>
......
<script setup lang="ts">
import { computed, ref, watch, nextTick } from 'vue'
import CustomModal from '@/components/custom-modal/custom-modal.vue'
import { fetchCustomEventSource } from '@/composables/useEventSource'
import { usePersonalAppConfigStore } from '@/store/modules/personal-app-config'
import { InputInst } from 'naive-ui'
import { useThrottleFn } from '@vueuse/core'
interface Props {
modalTitle: string
isShowModal: boolean
btnLoading: boolean
}
interface Emits {
(e: 'update:isShowModal', value: boolean): void
(e: 'comfirm', value: string): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const personalAppConfigStore = usePersonalAppConfigStore()
const agentSystemInputRef = ref<InputInst | null>(null)
const agentSystem = ref('')
const generateAgentSystemLoading = ref(false)
let controller: AbortController | null = null
const showModal = computed({
get() {
return props.isShowModal
},
set(value: boolean) {
emit('update:isShowModal', value)
},
})
watch(
() => showModal.value,
() => {
showModal.value && handleGenerateAgentSystem()
},
)
const isDisabledBtn = computed(() => {
return !agentSystem.value || generateAgentSystemLoading.value
})
function handleGenerateAgentSystem() {
agentSystem.value = ''
generateAgentSystemLoading.value = true
controller = new AbortController()
fetchCustomEventSource({
path: '/api/rest/agentApplicationInfoRest/createAgentSystem.json',
payload: {
input: personalAppConfigStore.baseInfo.agentSystem,
},
controller,
onMessage: (data: any) => {
if (data === '[DONE]') {
blockMessageResponse()
return
}
if (data) {
agentSystem.value += data
useThrottleFn(
() => {
nextTick(() => {
agentSystemInputRef.value!.textareaElRef!.scrollTop =
agentSystemInputRef.value?.textareaElRef?.scrollHeight || 0
})
},
200,
true,
)()
}
},
onRequestError: () => {
blockMessageResponse()
},
onError: () => {
blockMessageResponse()
},
onFinally: () => {
controller = null
},
})
}
function blockMessageResponse() {
controller?.abort()
generateAgentSystemLoading.value = false
}
function handleCloseModal() {
blockMessageResponse()
}
function handleAdditionalPrompt() {
emit('comfirm', agentSystem.value)
}
</script>
<template>
<CustomModal
v-model:is-show="showModal"
:title="modalTitle"
:btn-loading="btnLoading"
:btn-disabled="isDisabledBtn"
:width="640"
:height="610"
confirm-btn-text="使 用"
@close="handleCloseModal"
@confirm="handleAdditionalPrompt"
>
<template #content>
<div>
<NInput
ref="agentSystemInputRef"
v-model:value="agentSystem"
type="textarea"
:rows="18"
:disabled="generateAgentSystemLoading"
placeholder=""
class="rounded-lg!"
/>
<div class="mt-2.5">
<NButton :disabled="generateAgentSystemLoading" class="rounded-md!" @click="handleGenerateAgentSystem">
重新生成
</NButton>
</div>
</div>
</template>
</CustomModal>
</template>
......@@ -135,6 +135,11 @@ function handleSwtichAgentAppOption(currentTabKey: string) {
}
async function handlePublishApplication() {
if (!personalAppConfig.value.baseInfo.agentTitle) {
window.$message.warning('应用名称不能为空')
return
}
publishBtnloading.value = true
const res = await fetchPublishApplication(personalAppConfig.value).finally(() => (publishBtnloading.value = false))
......
......@@ -59,8 +59,8 @@ export function createPersonalAppColumn(handlePersonalAppTableAction: (actionTyp
props: { placement: 'top' },
},
{
trigger: () => h('span', {}, row.baseInfo.agentTitle || '我的Agent应用'),
default: () => h('span', {}, row.baseInfo.agentTitle || '我的Agent应用'),
trigger: () => h('span', {}, row.baseInfo.agentTitle || '--'),
default: () => h('span', {}, row.baseInfo.agentTitle || '--'),
},
),
],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment