|
|
@@ -0,0 +1,178 @@
|
|
|
+<template>
|
|
|
+ <PagingTable url="/story/templates" :where="where" ref="table">
|
|
|
+ <template #filter>
|
|
|
+ <ElButton :icon="Plus" @click="onEdit()">添加</ElButton>
|
|
|
+ </template>
|
|
|
+ <ElTableColumn prop="id" label="#" width="80" />
|
|
|
+ <ElTableColumn prop="name" label="名称" min-width="120" />
|
|
|
+ <ElTableColumn prop="createdAt" label="创建时间" :formatter="timeFormatter" width="150" />
|
|
|
+ <ElTableColumn label="操作" align="center" width="250">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <ElButton @click="onEdit(row)">编辑</ElButton>
|
|
|
+ <!-- <ElButton @click="onTest(row)">测试</ElButton> -->
|
|
|
+ <ElButton type="danger" @click="onDelete(row)">删除</ElButton>
|
|
|
+ </template>
|
|
|
+ </ElTableColumn>
|
|
|
+ </PagingTable>
|
|
|
+ <EditDialog
|
|
|
+ v-model="showEditDialog"
|
|
|
+ :model="model"
|
|
|
+ :rules="rules"
|
|
|
+ :on-submit="submit"
|
|
|
+ @success="table.refresh()"
|
|
|
+ label-width="120px"
|
|
|
+ width="800px"
|
|
|
+ >
|
|
|
+ <ElFormItem prop="name" label="名称">
|
|
|
+ <ElInput v-model="model.name" placeholder="请输入名称" />
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem prop="firstPrompt" label="配置">
|
|
|
+ <el-tabs v-model="tab" class="w-full">
|
|
|
+ <el-tab-pane label="初始" name="first">
|
|
|
+ <div class="p-4 rounded bg-neutral-100 dark:border-neutral-900">
|
|
|
+ <div class="flex items-center mb-4" v-for="(item, i) in model.firstVariables" :key="i">
|
|
|
+ <span class="w-12 text-right">参数名</span>
|
|
|
+ <ElInput class="!w-32 ml-1" v-model="item.name" placeholder="请输入参数名" />
|
|
|
+ <span class="w-12 text-right">描述</span>
|
|
|
+ <ElInput class="!w-48 ml-1" v-model="item.description" placeholder="请输入描述" />
|
|
|
+ <ElButton
|
|
|
+ class="ml-2"
|
|
|
+ type="danger"
|
|
|
+ :icon="X"
|
|
|
+ link
|
|
|
+ @click="removeVariable('firstVariables', i)"
|
|
|
+ ></ElButton>
|
|
|
+ </div>
|
|
|
+ <ElButton :icon="Plus" @click="addVariable('firstVariables')"></ElButton>
|
|
|
+ </div>
|
|
|
+ <ElInput v-model="model.firstPrompt" type="textarea" placeholder="请输入初始提示词" autosize />
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane label="继续" name="second">
|
|
|
+ <div class="p-4 rounded bg-neutral-100 dark:border-neutral-900">
|
|
|
+ <div class="flex items-center mb-4" v-for="(item, i) in model.continueVariables" :key="i">
|
|
|
+ <span class="w-12 text-right">参数名</span>
|
|
|
+ <ElInput class="!w-32 ml-1" v-model="item.name" placeholder="请输入参数名" />
|
|
|
+ <span class="w-12 text-right">描述</span>
|
|
|
+ <ElInput class="!w-48 ml-1" v-model="item.description" placeholder="请输入描述" />
|
|
|
+ <ElButton
|
|
|
+ class="ml-2"
|
|
|
+ type="danger"
|
|
|
+ :icon="X"
|
|
|
+ link
|
|
|
+ @click="removeVariable('continueVariables', i)"
|
|
|
+ ></ElButton>
|
|
|
+ </div>
|
|
|
+ <ElButton :icon="Plus" @click="addVariable('continueVariables')"></ElButton>
|
|
|
+ </div>
|
|
|
+ <ElInput v-model="model.continuePrompt" type="textarea" placeholder="请输入继续提示词" autosize />
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane label="结束" name="third">
|
|
|
+ <div class="p-4 rounded bg-neutral-100 dark:border-neutral-900">
|
|
|
+ <div class="flex items-center mb-4" v-for="(item, i) in model.endVariables" :key="i">
|
|
|
+ <span class="w-12 text-right">参数名</span>
|
|
|
+ <ElInput class="!w-32 ml-1" v-model="item.name" placeholder="请输入参数名" />
|
|
|
+ <span class="w-12 text-right">描述</span>
|
|
|
+ <ElInput class="!w-48 ml-1" v-model="item.description" placeholder="请输入描述" />
|
|
|
+ <ElButton
|
|
|
+ class="ml-2"
|
|
|
+ type="danger"
|
|
|
+ :icon="X"
|
|
|
+ link
|
|
|
+ @click="removeVariable('endVariables', i)"
|
|
|
+ ></ElButton>
|
|
|
+ </div>
|
|
|
+ <ElButton :icon="Plus" @click="addVariable('endVariables')"></ElButton>
|
|
|
+ </div>
|
|
|
+ <ElInput v-model="model.endPrompt" type="textarea" placeholder="请输入结束提示词" autosize />
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </ElFormItem>
|
|
|
+ </EditDialog>
|
|
|
+ <ElDialog title="测试" v-model="showTestDialog" width="800px">
|
|
|
+ <ElForm :model="testVariables" label-width="120" label-position="right" inline ref="testForm" :rules="testRuls">
|
|
|
+ <ElFormItem v-for="(item, i) in seleted?.variables" :key="i" :label="item.description" :prop="item.name">
|
|
|
+ <ElInput v-model="testVariables[item.name]" />
|
|
|
+ </ElFormItem>
|
|
|
+ </ElForm>
|
|
|
+ <ElButton @click="startTest">开始</ElButton>
|
|
|
+ </ElDialog>
|
|
|
+</template>
|
|
|
+<script setup>
|
|
|
+import { computed, ref } from 'vue'
|
|
|
+import PagingTable from '@/components/PagingTable.vue'
|
|
|
+import { useTimeFormatter } from '@/utils/formatter'
|
|
|
+import { Plus, X } from '@vicons/tabler'
|
|
|
+import EditDialog from '@/components/EditDialog.vue'
|
|
|
+import { setupEditDialog } from '@/utils/editDialog'
|
|
|
+import EnumSelect from '@/components/EnumSelect.vue'
|
|
|
+import { UserRole } from '@/enums'
|
|
|
+import { http } from '@/plugins/http'
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
+import { useClipboard } from '@vueuse/core'
|
|
|
+
|
|
|
+const where = ref({})
|
|
|
+const timeFormatter = useTimeFormatter()
|
|
|
+const table = ref(null)
|
|
|
+const model = ref({
|
|
|
+ variables: []
|
|
|
+})
|
|
|
+const rules = {
|
|
|
+ name: [{ required: true, message: '请输入名称', trigger: 'blur' }]
|
|
|
+}
|
|
|
+const { showEditDialog, onEdit } = setupEditDialog(model)
|
|
|
+async function submit() {
|
|
|
+ await http.put(model.value.id ? `/story/templates/${model.value.id}` : '/story/templates', model.value)
|
|
|
+ ElMessage.success('保存成功')
|
|
|
+}
|
|
|
+async function onDelete(row) {
|
|
|
+ await ElMessageBox.confirm('确认删除?', '删除', { type: 'warning' })
|
|
|
+ await http.delete(`/story/templates/${row.id}`)
|
|
|
+ ElMessage.success('删除成功')
|
|
|
+ table.value.refresh()
|
|
|
+}
|
|
|
+function addVariable(v) {
|
|
|
+ model.value[v] = model.value[v] || []
|
|
|
+ model.value[v].push({})
|
|
|
+}
|
|
|
+function removeVariable(v, index) {
|
|
|
+ model.value[v].splice(index, 1)
|
|
|
+}
|
|
|
+const tab = ref('first')
|
|
|
+
|
|
|
+const showTestDialog = ref(false)
|
|
|
+const seleted = ref(null)
|
|
|
+const testForm = ref(null)
|
|
|
+const testRuls = computed(() => {
|
|
|
+ const rules = {}
|
|
|
+ seleted.value?.variables?.forEach((item) => {
|
|
|
+ rules[item.name] = [{ required: true, message: '请输入' + item.description, trigger: 'blur' }]
|
|
|
+ })
|
|
|
+ return rules
|
|
|
+})
|
|
|
+
|
|
|
+const testVariables = ref({
|
|
|
+ variables: {}
|
|
|
+})
|
|
|
+const testResults = ref([])
|
|
|
+function onTest(row) {
|
|
|
+ seleted.value = row
|
|
|
+ testVariables.value = {}
|
|
|
+ testResults.value = []
|
|
|
+ testForm.value?.clearValidate()
|
|
|
+ showTestDialog.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const testLoading = ref(false)
|
|
|
+async function startTest() {
|
|
|
+ await testForm.value.validate()
|
|
|
+ const data = { templateId: seleted.value.id, variables: testVariables.value }
|
|
|
+ testLoading.value = true
|
|
|
+ try {
|
|
|
+ const res = await http.post(`/story/start`, data)
|
|
|
+ testResults.value.push(res)
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error(error.message)
|
|
|
+ }
|
|
|
+ testLoading.value = false
|
|
|
+}
|
|
|
+</script>
|