feat: create tag function

v3.2
wangdan-fit2cloud 2025-10-17 18:03:37 +08:00
parent 6eaca43d6e
commit 62873d882f
11 changed files with 260 additions and 200 deletions

View File

@ -450,18 +450,18 @@ export default {
placeholder: '请输入表达式', placeholder: '请输入表达式',
}, },
}, },
parameterExtractionNode: { parameterExtractionNode: {
label: '参数提取', label: '參數提取',
text: '利用 AI 模型提取结构化参数', text: '利用 AI 模型提取結構化參數',
result: '果', result: '果',
selectVariables: { selectVariables: {
label: '选择变量', label: '選擇變量',
placeholder: '请选择变量', placeholder: '請選擇變量',
}, },
extractParameters: { extractParameters: {
label: '提取参数', label: '提取參數',
desc: '描述', desc: '描述',
parameterType: '参数类型', parameterType: '參數類型',
}, },
}, },
}, },

View File

@ -424,16 +424,16 @@ export default {
}, },
}, },
parameterExtractionNode: { parameterExtractionNode: {
label: 'Parameter Extraction', label: '參數提取',
text: 'Extract structured parameters using AI model', text: ' ',
result: 'Result', result: '結果',
selectVariables: { selectVariables: {
label: 'Select Variables', label: ' ',
placeholder: 'Please select variables', placeholder: '請選擇要提取的參數',
}, },
extractParameters: { extractParameters: {
label: 'Extract Parameters', label: '提取參數',
desc: 'Description', desc: '從文本中提取參數',
parameterType: 'Parameter Type', parameterType: 'Parameter Type',
}, },
}, },

View File

@ -1,9 +1,5 @@
<template> <template>
<el-dialog <el-dialog v-model="dialogVisible" :title="$t('views.document.tag.add')" :before-close="close">
v-model="dialogVisible"
:title="$t('views.document.tag.add')"
:before-close="close"
>
<el-form <el-form
ref="FormRef" ref="FormRef"
:model="{ tags }" :model="{ tags }"
@ -12,34 +8,52 @@
@submit.prevent @submit.prevent
> >
<div class="flex-between flex" v-for="(tag, index) in tags" :key="tag"> <div class="flex-between flex" v-for="(tag, index) in tags" :key="tag">
<el-form-item :label="index === 0? $t('views.document.tag.key') : ''" <el-form-item
:prop="`tags.${index}.key`" :label="index === 0 ? $t('views.document.tag.key') : ''"
style="width: 50%" :prop="`tags.${index}.key`"
:rules="{ required: true, message: $t('views.document.tag.requiredMessage1'), trigger: 'blur' }"> style="width: 50%"
:rules="{
required: true,
message: $t('views.document.tag.requiredMessage1'),
trigger: 'blur',
}"
>
<el-select v-model="tag.key" @change="tagKeyChange(tag)" filterable> <el-select v-model="tag.key" @change="tagKeyChange(tag)" filterable>
<el-option v-for="op in keyOptions" :key="op" :value="op.key" <el-option
:label="op.key"></el-option> v-for="op in keyOptions"
:key="op"
:value="op.key"
:label="op.key"
></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="index === 0? $t('views.document.tag.value') : ''" <el-form-item
:prop="`tags.${index}.value`" :label="index === 0 ? $t('views.document.tag.value') : ''"
style="width: 50%" :prop="`tags.${index}.value`"
:rules="{ required: true, message: $t('views.document.tag.requiredMessage2'), trigger: 'blur' }"> style="width: 50%"
:rules="{
required: true,
message: $t('views.document.tag.requiredMessage2'),
trigger: 'blur',
}"
>
<el-select v-model="tag.value" filterable> <el-select v-model="tag.value" filterable>
<el-option v-for="op in tag.valueOptions" :key="op" :value="op.id" <el-option
:label="op.value"></el-option> v-for="op in tag.valueOptions"
:key="op"
:value="op.id"
:label="op.value"
></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> </div>
</el-form> </el-form>
<el-button link type="primary" @click="add">
<AppIcon iconName="app-add-outlined" class="mr-4" />
{{ $t('common.add') }}
</el-button>
<div class="mt-20">
<el-button link type="primary" @click="add">
<AppIcon iconName="app-add-outlined" class="mr-4"/>
{{ $t('common.add') }}
</el-button>
</div>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="close">{{ $t('common.cancel') }}</el-button> <el-button @click="close">{{ $t('common.cancel') }}</el-button>
@ -50,14 +64,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import AppIcon from "@/components/app-icon/AppIcon.vue"; import AppIcon from '@/components/app-icon/AppIcon.vue'
const emit = defineEmits(['addTags']) const emit = defineEmits(['addTags'])
const props = defineProps({ const props = defineProps({
knowledgeTags: { knowledgeTags: {
type: Array, type: Array,
default: () => [] default: () => [],
} },
}) })
const FormRef = ref() const FormRef = ref()
@ -78,7 +92,10 @@ function tagKeyChange(tag: any) {
const submit = () => { const submit = () => {
FormRef.value.validate((valid: boolean) => { FormRef.value.validate((valid: boolean) => {
if (!valid) return if (!valid) return
emit('addTags', tags.value.map(tag => tag.value)) emit(
'addTags',
tags.value.map((tag) => tag.value),
)
}) })
} }
@ -92,6 +109,6 @@ const close = () => {
dialogVisible.value = false dialogVisible.value = false
} }
defineExpose({open, close}) defineExpose({ open, close })
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -1,107 +0,0 @@
<template>
<el-dialog
v-model="dialogVisible"
:title="$t('views.document.tag.create')"
:before-close="close"
>
<el-form
ref="FormRef"
:model="{ tags }"
label-position="top"
require-asterisk-position="right"
@submit.prevent
>
<div class="flex-between" v-for="(tag, index) in tags" :key="tag">
<el-form-item :label="index === 0? $t('views.document.tag.key') : ''"
:prop="`tags.${index}.key`"
style="width: 50%"
:rules="{ required: true, message: $t('views.document.tag.requiredMessage1'), trigger: 'blur' }">
<el-input v-model="tag.key" :disabled="currentTagKey"></el-input>
</el-form-item>
<el-form-item :label="index === 0? $t('views.document.tag.value') : ''"
:prop="`tags.${index}.value`"
style="width: 50%"
:rules="{ required: true, message: $t('views.document.tag.requiredMessage2'), trigger: 'blur' }">
<el-input v-model="tag.value"></el-input>
</el-form-item>
</div>
</el-form>
<div class="mt-20">
<el-button link type="primary" @click="add">
<AppIcon iconName="app-add-outlined" class="mr-4"/>
{{ $t('common.add') }}
</el-button>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submit">{{ $t('common.confirm') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import AppIcon from "@/components/app-icon/AppIcon.vue";
import { useRoute } from "vue-router";
import { loadSharedApi } from "@/utils/dynamics-api/shared-api.ts";
import { cloneDeep } from "lodash";
const route = useRoute()
const {
params: {id}, // idknowledgeID
} = route as any
const emit = defineEmits(['refresh'])
const apiType = computed(() => {
if (route.path.includes('shared')) {
return 'systemShare'
} else if (route.path.includes('resource-management')) {
return 'systemManage'
} else {
return 'workspace'
}
})
const FormRef = ref()
const loading = ref(false)
const dialogVisible = ref<boolean>(false)
const currentTagKey = ref(null)
const tags = ref<Array<any>>([])
const add = () => {
if (currentTagKey.value) {
tags.value.push({key: currentTagKey.value})
} else {
tags.value.push({})
}
}
const submit = () => {
FormRef.value.validate((valid: boolean) => {
if (!valid) return
loadSharedApi({type: 'knowledge', systemType: apiType.value})
.postTags(id, tags.value, loading)
.then((res: any) => {
close()
emit('refresh')
})
})
}
const open = (row?: any) => {
const currentRow = cloneDeep(row)
dialogVisible.value = true
currentTagKey.value = currentRow ? currentRow.key : null
tags.value = currentRow ? [{...{key: currentRow.key}}] : [{}]
}
const close = () => {
dialogVisible.value = false
}
defineExpose({open, close})
</script>
<style lang="scss" scoped></style>

View File

@ -685,8 +685,8 @@ import { TaskType, State } from '@/utils/status'
import { t } from '@/locales' import { t } from '@/locales'
import permissionMap from '@/permission' import permissionMap from '@/permission'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api' import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
import TagDrawer from "./component/TagDrawer.vue"; import TagDrawer from "./tag/TagDrawer.vue";
import TagSettingDrawer from "./component/TagSettingDrawer.vue"; import TagSettingDrawer from "./tag/TagSettingDrawer.vue";
import AddTagDialog from "@/views/document/component/AddTagDialog.vue"; import AddTagDialog from "@/views/document/component/AddTagDialog.vue";
const route = useRoute() const route = useRoute()

View File

@ -0,0 +1,146 @@
<template>
<el-dialog v-model="dialogVisible" :title="$t('views.document.tag.create')" :before-close="close">
<el-form
ref="FormRef"
:model="{ tags }"
label-position="top"
require-asterisk-position="right"
@submit.prevent
>
<el-scrollbar>
<el-row :gutter="8" align="bottom" style="margin-right: 10px" class="tag-list-max-list">
<template v-for="(tag, index) in tags" :key="tag">
<el-col :span="12">
<el-form-item
:label="index === 0 ? $t('views.document.tag.key') : ''"
:prop="`tags.${index}.key`"
:rules="{
required: true,
message: $t('views.document.tag.requiredMessage1'),
trigger: 'blur',
}"
>
<el-input
v-model="tag.key"
:disabled="currentTagKey"
class="w-full"
:placeholder="$t('views.document.tag.requiredMessage1')"
></el-input>
</el-form-item>
</el-col>
<el-col :span="11">
<el-form-item
:label="index === 0 ? $t('views.document.tag.value') : ''"
:prop="`tags.${index}.value`"
:rules="{
required: true,
message: $t('views.document.tag.requiredMessage2'),
trigger: 'blur',
}"
class="w-full"
>
<el-input
v-model="tag.value"
:placeholder="$t('views.document.tag.requiredMessage2')"
></el-input>
</el-form-item>
</el-col>
<el-col :span="1">
<el-button
:disabled="index === 0"
link
type="info"
@click="deleteTag(index)"
class="mb-24"
>
<AppIcon iconName="app-delete"></AppIcon>
</el-button>
</el-col>
</template>
</el-row>
</el-scrollbar>
</el-form>
<el-button link type="primary" @click="add">
<AppIcon iconName="app-add-outlined" class="mr-4" />
{{ $t('common.add') }}
</el-button>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submit">{{ $t('common.confirm') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import AppIcon from '@/components/app-icon/AppIcon.vue'
import { useRoute } from 'vue-router'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api.ts'
import { cloneDeep } from 'lodash'
const route = useRoute()
const {
params: { id }, // idknowledgeID
} = route as any
const emit = defineEmits(['refresh'])
const apiType = computed(() => {
if (route.path.includes('shared')) {
return 'systemShare'
} else if (route.path.includes('resource-management')) {
return 'systemManage'
} else {
return 'workspace'
}
})
const FormRef = ref()
const loading = ref(false)
const dialogVisible = ref<boolean>(false)
const currentTagKey = ref(null)
const tags = ref<Array<any>>([])
const add = () => {
if (currentTagKey.value) {
tags.value.push({ key: currentTagKey.value })
} else {
tags.value.push({})
}
}
const deleteTag = (index: number) => {
tags.value.splice(index, 1)
}
const submit = () => {
FormRef.value.validate((valid: boolean) => {
if (!valid) return
loadSharedApi({ type: 'knowledge', systemType: apiType.value })
.postTags(id, tags.value, loading)
.then((res: any) => {
close()
emit('refresh')
})
})
}
const open = (row?: any) => {
const currentRow = cloneDeep(row)
dialogVisible.value = true
currentTagKey.value = currentRow ? currentRow.key : null
tags.value = currentRow ? [{ ...{ key: currentRow.key } }] : [{}]
}
const close = () => {
dialogVisible.value = false
}
defineExpose({ open, close })
</script>
<style lang="scss" scoped>
.tag-list-max-list {
max-height: calc(100vh - 260px);
}
</style>

View File

@ -3,11 +3,10 @@
<template #header> <template #header>
<h4>{{ $t('views.document.tag.label') }}</h4> <h4>{{ $t('views.document.tag.label') }}</h4>
</template> </template>
<div class="flex-between"> <div class="flex-between mb-16">
<div> <div>
<el-button type="primary" @click="openCreateTagDialog()">{{ <el-button type="primary" @click="openCreateTagDialog()"
$t('views.document.tag.create') >{{ $t('views.document.tag.create') }}
}}
</el-button> </el-button>
<el-button :disabled="multipleSelection.length === 0" @click="batchDelete"> <el-button :disabled="multipleSelection.length === 0" @click="batchDelete">
{{ $t('common.delete') }} {{ $t('common.delete') }}
@ -19,6 +18,7 @@
class="w-240" class="w-240"
@change="getList" @change="getList"
clearable clearable
:placeholder="$t('common.search')"
/> />
</div> </div>
<el-table <el-table
@ -27,21 +27,24 @@
v-loading="loading" v-loading="loading"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
> >
<el-table-column type="selection" width="55"/> <el-table-column type="selection" width="55" />
<el-table-column :label="$t('views.document.tag.key')"> <el-table-column :label="$t('views.document.tag.key')">
<template #default="{ row }"> <template #default="{ row }">
<div class="flex-between"> <div class="flex-between">
{{ row.key }} {{ row.key }}
<div> <div>
<el-button link> <el-button link>
<AppIcon iconName="app-add-outlined" class="mr-4" <AppIcon
@click="openCreateTagDialog(row)"/> iconName="app-add-outlined"
class="mr-4"
@click="openCreateTagDialog(row)"
/>
</el-button> </el-button>
<el-button link> <el-button link>
<AppIcon iconName="app-edit" class="mr-4" @click="editTagKey(row)"/> <AppIcon iconName="app-edit" class="mr-4" @click="editTagKey(row)" />
</el-button> </el-button>
<el-button link> <el-button link>
<AppIcon iconName="app-delete" class="mr-4" @click="delTag(row)"/> <AppIcon iconName="app-delete" class="mr-4" @click="delTag(row)" />
</el-button> </el-button>
</div> </div>
</div> </div>
@ -53,10 +56,10 @@
{{ row.value }} {{ row.value }}
<div> <div>
<el-button link> <el-button link>
<AppIcon iconName="app-edit" class="mr-4" @click="editTagValue(row)"/> <AppIcon iconName="app-edit" class="mr-4" @click="editTagValue(row)" />
</el-button> </el-button>
<el-button link> <el-button link>
<AppIcon iconName="app-delete" class="mr-4" @click="delTagValue(row)"/> <AppIcon iconName="app-delete" class="mr-4" @click="delTagValue(row)" />
</el-button> </el-button>
</div> </div>
</div> </div>
@ -64,24 +67,24 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-drawer> </el-drawer>
<CreateTagDialog ref="createTagDialogRef" @refresh="getList"/> <CreateTagDialog ref="createTagDialogRef" @refresh="getList" />
<EditTagDialog ref="editTagDialogRef" @refresh="getList"/> <EditTagDialog ref="editTagDialogRef" @refresh="getList" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { loadSharedApi } from "@/utils/dynamics-api/shared-api.ts" import { loadSharedApi } from '@/utils/dynamics-api/shared-api.ts'
import CreateTagDialog from "./CreateTagDialog.vue" import CreateTagDialog from './CreateTagDialog.vue'
import { MsgConfirm } from "@/utils/message.ts"; import { MsgConfirm } from '@/utils/message.ts'
import { t } from "@/locales"; import { t } from '@/locales'
import EditTagDialog from "@/views/document/component/EditTagDialog.vue"; import EditTagDialog from '@/views/document/tag/EditTagDialog.vue'
const emit = defineEmits(['refresh']) const emit = defineEmits(['refresh'])
const route = useRoute() const route = useRoute()
const { const {
params: {id}, // idknowledgeID params: { id }, // idknowledgeID
} = route as any } = route as any
const apiType = computed(() => { const apiType = computed(() => {
@ -109,7 +112,7 @@ const tableData = computed(() => {
id: value.id, id: value.id,
key: tag.key, key: tag.key,
value: value.value, value: value.value,
keyIndex: index // keyIndex: index, //
}) })
}) })
} }
@ -117,33 +120,31 @@ const tableData = computed(() => {
return result return result
}) })
// //
const spanMethod = ({row, column, rowIndex, columnIndex}: any) => { const spanMethod = ({ row, column, rowIndex, columnIndex }: any) => {
if (columnIndex === 0 || columnIndex === 1) { // key (1) if (columnIndex === 0 || columnIndex === 1) {
// key (1)
if (row.keyIndex === 0) { if (row.keyIndex === 0) {
// key // key
const sameKeyCount = tableData.value.filter(item => item.key === row.key).length const sameKeyCount = tableData.value.filter((item) => item.key === row.key).length
return { return {
rowspan: sameKeyCount, rowspan: sameKeyCount,
colspan: 1 colspan: 1,
} }
} else { } else {
return { return {
rowspan: 0, rowspan: 0,
colspan: 0 colspan: 0,
} }
} }
} }
} }
const multipleSelection = ref<any[]>([]) const multipleSelection = ref<any[]>([])
const handleSelectionChange = (val: any[]) => { const handleSelectionChange = (val: any[]) => {
multipleSelection.value = val multipleSelection.value = val
} }
const createTagDialogRef = ref() const createTagDialogRef = ref()
function openCreateTagDialog(row?: any) { function openCreateTagDialog(row?: any) {
@ -156,15 +157,14 @@ function batchDelete() {
confirmButtonClass: 'danger', confirmButtonClass: 'danger',
}) })
.then(() => { .then(() => {
const tagsToDelete = multipleSelection.value.map(item => item.id) const tagsToDelete = multipleSelection.value.map((item) => item.id)
loadSharedApi({type: 'knowledge', systemType: apiType.value}) loadSharedApi({ type: 'knowledge', systemType: apiType.value })
.delMulTag(id, tagsToDelete) .delMulTag(id, tagsToDelete)
.then(() => { .then(() => {
getList() getList()
}) })
}) })
.catch(() => { .catch(() => {})
})
} }
const editTagDialogRef = ref() const editTagDialogRef = ref()
@ -179,14 +179,13 @@ function delTag(row: any) {
confirmButtonClass: 'danger', confirmButtonClass: 'danger',
}) })
.then(() => { .then(() => {
loadSharedApi({type: 'knowledge', systemType: apiType.value}) loadSharedApi({ type: 'knowledge', systemType: apiType.value })
.delTag(id, row.id, 'key') .delTag(id, row.id, 'key')
.then(() => { .then(() => {
getList() getList()
}) })
}) })
.catch(() => { .catch(() => {})
})
} }
function editTagValue(row: any) { function editTagValue(row: any) {
@ -194,26 +193,29 @@ function editTagValue(row: any) {
} }
function delTagValue(row: any) { function delTagValue(row: any) {
MsgConfirm(t('views.document.tag.deleteConfirm') + row.key + '-' + row.value, t('views.document.tag.deleteTip'), { MsgConfirm(
confirmButtonText: t('common.delete'), t('views.document.tag.deleteConfirm') + row.key + '-' + row.value,
confirmButtonClass: 'danger', t('views.document.tag.deleteTip'),
}) {
confirmButtonText: t('common.delete'),
confirmButtonClass: 'danger',
},
)
.then(() => { .then(() => {
loadSharedApi({type: 'knowledge', systemType: apiType.value}) loadSharedApi({ type: 'knowledge', systemType: apiType.value })
.delTag(id, row.id, 'one') .delTag(id, row.id, 'one')
.then(() => { .then(() => {
getList() getList()
}) })
}) })
.catch(() => { .catch(() => {})
})
} }
function getList() { function getList() {
const params = { const params = {
...(filterText.value && {name: filterText.value}), ...(filterText.value && { name: filterText.value }),
} }
loadSharedApi({type: 'knowledge', systemType: apiType.value}) loadSharedApi({ type: 'knowledge', systemType: apiType.value })
.getTags(id, params, loading) .getTags(id, params, loading)
.then((res: any) => { .then((res: any) => {
tags.value = res.data tags.value = res.data

View File

@ -94,8 +94,9 @@
<AppIcon iconName="app-delete"></AppIcon> <AppIcon iconName="app-delete"></AppIcon>
</el-button> </el-button>
</el-col> </el-col>
</el-row> </template </el-row>
></el-form> </template>
</el-form>
<el-button link type="primary" @click="addCondition()"> <el-button link type="primary" @click="addCondition()">
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon> <AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>

View File

@ -94,8 +94,9 @@
<AppIcon iconName="app-delete"></AppIcon> <AppIcon iconName="app-delete"></AppIcon>
</el-button> </el-button>
</el-col> </el-col>
</el-row> </template </el-row>
></el-form> </template>
</el-form>
<el-button link type="primary" @click="addCondition()"> <el-button link type="primary" @click="addCondition()">
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon> <AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>