|
@@ -1,6 +1,14 @@
|
|
|
<template>
|
|
<template>
|
|
|
<el-scrollbar class="w-full box-border p-12px">
|
|
<el-scrollbar class="w-full box-border p-12px">
|
|
|
<div class="qc-setter">
|
|
<div class="qc-setter">
|
|
|
|
|
+ <section class="section-block">
|
|
|
|
|
+ <div class="w-full flex items-center justify-between beautify">
|
|
|
|
|
+ <label class="text-14px font-bold text-gray-700">{{ texts.input }}</label>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <VarInput v-model="formData.query" class="w-full" placeholder="输入/选择变量" />
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 分类 -->
|
|
|
<section class="section-block">
|
|
<section class="section-block">
|
|
|
<div class="section-header">
|
|
<div class="section-header">
|
|
|
<label class="section-title">{{ texts.classes }}</label>
|
|
<label class="section-title">{{ texts.classes }}</label>
|
|
@@ -9,67 +17,54 @@
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div class="w-full flex items-center justify-between beautify">
|
|
|
|
|
- <label class="text-14px font-bold text-gray-700">{{ texts.input }}</label>
|
|
|
|
|
|
|
+ <div v-if="!formData.classes?.length" class="empty-state">
|
|
|
|
|
+ <div class="empty-desc">{{ texts.empty }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <VarInput v-model="formData.query" class="w-full" :rows="3" placeholder="输入/选择变量" />
|
|
|
|
|
- </section>
|
|
|
|
|
|
|
|
|
|
- <section class="section-block">
|
|
|
|
|
- <el-collapse>
|
|
|
|
|
- <el-collapse-item name="0">
|
|
|
|
|
- <template #title>
|
|
|
|
|
- <div class="flex items-center justify-between beautify">
|
|
|
|
|
- <label class="text-14px font-bold text-gray-700">输出变量</label>
|
|
|
|
|
|
|
+ <VueDraggable
|
|
|
|
|
+ v-else
|
|
|
|
|
+ v-model="formData.classes"
|
|
|
|
|
+ :animation="150"
|
|
|
|
|
+ handle=".handle"
|
|
|
|
|
+ @end="handleSortEnd"
|
|
|
|
|
+ class="class-list"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div v-for="(item, index) in formData.classes" :key="item.id" class="class-card">
|
|
|
|
|
+ <div class="class-card__header">
|
|
|
|
|
+ <div class="class-card__title">
|
|
|
|
|
+ <Icon icon="lucide:grip-vertical" :size="16" class="handle drag-icon" />
|
|
|
|
|
+ <span class="class-index">{{ item.name }}</span>
|
|
|
</div>
|
|
</div>
|
|
|
- </template>
|
|
|
|
|
- <div>
|
|
|
|
|
- <div v-if="!formData.classes?.length" class="empty-state">
|
|
|
|
|
- <div class="empty-desc">{{ texts.empty }}</div>
|
|
|
|
|
|
|
+ <div class="class-card__actions">
|
|
|
|
|
+ <IconButton
|
|
|
|
|
+ link
|
|
|
|
|
+ icon="lucide:copy"
|
|
|
|
|
+ class="text-#667085"
|
|
|
|
|
+ @click="handleDuplicateClass(index)"
|
|
|
|
|
+ />
|
|
|
|
|
+ <IconButton
|
|
|
|
|
+ link
|
|
|
|
|
+ icon="lucide:trash-2"
|
|
|
|
|
+ class="text-#f04438 ml-0!"
|
|
|
|
|
+ @click="handleRemoveClass(index)"
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- <VueDraggable
|
|
|
|
|
- v-else
|
|
|
|
|
- v-model="formData.classes"
|
|
|
|
|
- :animation="150"
|
|
|
|
|
- handle=".handle"
|
|
|
|
|
- class="class-list"
|
|
|
|
|
- >
|
|
|
|
|
- <div v-for="(item, index) in formData.classes" :key="item.id" class="class-card">
|
|
|
|
|
- <div class="class-card__header">
|
|
|
|
|
- <div class="class-card__title">
|
|
|
|
|
- <Icon icon="lucide:grip-vertical" :size="16" class="handle drag-icon" />
|
|
|
|
|
- <span class="class-index">{{ item.name }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="class-card__actions">
|
|
|
|
|
- <IconButton
|
|
|
|
|
- link
|
|
|
|
|
- icon="lucide:copy"
|
|
|
|
|
- class="text-#667085"
|
|
|
|
|
- @click="handleDuplicateClass(index)"
|
|
|
|
|
- />
|
|
|
|
|
- <IconButton
|
|
|
|
|
- link
|
|
|
|
|
- icon="lucide:trash-2"
|
|
|
|
|
- class="text-#f04438 ml-0!"
|
|
|
|
|
- @click="handleRemoveClass(index)"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div class="class-card__body">
|
|
|
|
|
- <VarInput
|
|
|
|
|
- v-model="item.instruction"
|
|
|
|
|
- class="w-full"
|
|
|
|
|
- :rows="3"
|
|
|
|
|
- :placeholder="texts.classInstructionPlaceholder"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </VueDraggable>
|
|
|
|
|
|
|
+ <div class="class-card__body">
|
|
|
|
|
+ <VarInput
|
|
|
|
|
+ v-model="item.instruction"
|
|
|
|
|
+ class="w-full"
|
|
|
|
|
+ :rows="3"
|
|
|
|
|
+ :placeholder="texts.classInstructionPlaceholder"
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
- </el-collapse-item>
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </VueDraggable>
|
|
|
|
|
+ </section>
|
|
|
|
|
|
|
|
|
|
+ <section class="section-block">
|
|
|
|
|
+ <el-collapse>
|
|
|
<el-collapse-item name="1">
|
|
<el-collapse-item name="1">
|
|
|
<template #title>
|
|
<template #title>
|
|
|
<div class="flex items-center justify-between beautify">
|
|
<div class="flex items-center justify-between beautify">
|
|
@@ -112,7 +107,7 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { computed, watch } from 'vue'
|
|
|
|
|
|
|
+import { computed } from 'vue'
|
|
|
import { VueDraggable } from 'vue-draggable-plus'
|
|
import { VueDraggable } from 'vue-draggable-plus'
|
|
|
import { Icon, IconButton } from '@repo/ui'
|
|
import { Icon, IconButton } from '@repo/ui'
|
|
|
|
|
|
|
@@ -149,33 +144,33 @@ const texts = computed(() => ({
|
|
|
|
|
|
|
|
const formData = useSetterModel<QuestionClassifierData>(props, emit)
|
|
const formData = useSetterModel<QuestionClassifierData>(props, emit)
|
|
|
|
|
|
|
|
-watch(
|
|
|
|
|
- () => formData.value.classes,
|
|
|
|
|
- () => {
|
|
|
|
|
- formData.value.classes.forEach((c, index) => {
|
|
|
|
|
- c.id = `${props.id}_${index + 1}`
|
|
|
|
|
- c.name = c.name || `${texts.value.classPrefix}${index + 1}`
|
|
|
|
|
- })
|
|
|
|
|
- },
|
|
|
|
|
- { deep: true }
|
|
|
|
|
-)
|
|
|
|
|
-
|
|
|
|
|
const getId = () => {
|
|
const getId = () => {
|
|
|
const ids = formData.value.classes.map((c) => c.id.split('_')[1]).map(Number)
|
|
const ids = formData.value.classes.map((c) => c.id.split('_')[1]).map(Number)
|
|
|
const maxId = Math.max(...ids, 0)
|
|
const maxId = Math.max(...ids, 0)
|
|
|
return props.id + '_' + (maxId + 1)
|
|
return props.id + '_' + (maxId + 1)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const getClassName = (index: number) => `${texts.value.classPrefix}${index}`
|
|
|
|
|
+
|
|
|
const createClassItem = (index?: number): ClassItem => ({
|
|
const createClassItem = (index?: number): ClassItem => ({
|
|
|
id: index ? `${props.id}_${index}` : getId(),
|
|
id: index ? `${props.id}_${index}` : getId(),
|
|
|
- name: '',
|
|
|
|
|
|
|
+ name: index ? getClassName(index) : '',
|
|
|
instruction: ''
|
|
instruction: ''
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+const reorderClasses = () => {
|
|
|
|
|
+ formData.value.classes = (formData.value.classes || []).map((item, index) => ({
|
|
|
|
|
+ ...item,
|
|
|
|
|
+ id: `${props.id}_${index + 1}`,
|
|
|
|
|
+ name: getClassName(index + 1)
|
|
|
|
|
+ }))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const ensureDefaults = () => {
|
|
const ensureDefaults = () => {
|
|
|
formData.value.type ||= 'question-classifier'
|
|
formData.value.type ||= 'question-classifier'
|
|
|
formData.value.classes ||= [createClassItem(1), createClassItem(2), createClassItem(3)]
|
|
formData.value.classes ||= [createClassItem(1), createClassItem(2), createClassItem(3)]
|
|
|
formData.value.instruction ||= ''
|
|
formData.value.instruction ||= ''
|
|
|
|
|
+ reorderClasses()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ensureDefaults()
|
|
ensureDefaults()
|
|
@@ -185,10 +180,12 @@ const handleAddClass = () => {
|
|
|
formData.value.classes = []
|
|
formData.value.classes = []
|
|
|
}
|
|
}
|
|
|
formData.value.classes.push(createClassItem())
|
|
formData.value.classes.push(createClassItem())
|
|
|
|
|
+ reorderClasses()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const handleRemoveClass = (index: number) => {
|
|
const handleRemoveClass = (index: number) => {
|
|
|
formData.value.classes.splice(index, 1)
|
|
formData.value.classes.splice(index, 1)
|
|
|
|
|
+ reorderClasses()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const handleDuplicateClass = (index: number) => {
|
|
const handleDuplicateClass = (index: number) => {
|
|
@@ -199,6 +196,11 @@ const handleDuplicateClass = (index: number) => {
|
|
|
id: `class-${Date.now()}-${index}`
|
|
id: `class-${Date.now()}-${index}`
|
|
|
}
|
|
}
|
|
|
formData.value.classes.splice(index + 1, 0, copy)
|
|
formData.value.classes.splice(index + 1, 0, copy)
|
|
|
|
|
+ reorderClasses()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleSortEnd = () => {
|
|
|
|
|
+ reorderClasses()
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|