feat: 增加复制应用功能(#768)

This commit is contained in:
wangdan-fit2cloud 2024-08-19 11:24:19 +08:00 committed by wangdan-fit2cloud
parent 1fde17a718
commit 8e8ce795b2
4 changed files with 215 additions and 17 deletions

View File

@ -29,7 +29,8 @@ export default {
title: {
create: 'Create Application',
edit: 'Edit Settings',
info: 'Application Information'
info: 'Application Information',
copy: 'Copy Application'
},
form: {
appName: {
@ -73,7 +74,9 @@ export default {
create: 'Create',
createSuccess: 'Create Success',
save: 'Save',
saveSuccess: 'Save Success'
saveSuccess: 'Save Success',
copy: 'Copy',
copySuccess: 'Copy Success'
},
dialogues: {
addDataset: 'Add Related Knowledge Base',

View File

@ -28,7 +28,8 @@ export default {
title: {
create: '创建应用',
edit: '设置',
info: '应用信息'
info: '应用信息',
copy: '复制应用'
},
form: {
appName: {
@ -70,7 +71,9 @@ export default {
create: '创建',
createSuccess: '创建成功',
save: '保存',
saveSuccess: '保存成功'
saveSuccess: '保存成功',
copy: '复制',
copySuccess: '复制成功'
},
dialogues: {
addDataset: '添加关联知识库',

View File

@ -0,0 +1,172 @@
<template>
<el-dialog
:title="$t('views.application.applicationForm.title.copy')"
v-model="dialogVisible"
width="650"
append-to-body
>
<el-form
ref="applicationFormRef"
:model="applicationForm"
:rules="rules"
label-position="top"
require-asterisk-position="right"
>
<el-form-item :label="$t('views.application.applicationForm.form.appName.label')" prop="name">
<el-input
v-model="applicationForm.name"
maxlength="64"
:placeholder="$t('views.application.applicationForm.form.appName.placeholder')"
show-word-limit
/>
</el-form-item>
<el-form-item :label="$t('views.application.applicationForm.form.appDescription.label')">
<el-input
v-model="applicationForm.desc"
type="textarea"
:placeholder="$t('views.application.applicationForm.form.appDescription.placeholder')"
:rows="3"
maxlength="256"
show-word-limit
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click.prevent="dialogVisible = false" :loading="loading">
{{ $t('views.application.applicationForm.buttons.cancel') }}
</el-button>
<el-button type="primary" @click="submitValid(applicationFormRef)" :loading="loading">
{{ $t('views.application.applicationForm.buttons.copy') }}
</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, watch, reactive } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { cloneDeep } from 'lodash'
import type { ApplicationFormType } from '@/api/type/application'
import type { FormInstance, FormRules } from 'element-plus'
import applicationApi from '@/api/application'
import { MsgSuccess, MsgAlert } from '@/utils/message'
import { isWorkFlow } from '@/utils/application'
import { t } from '@/locales'
import useStore from '@/stores'
import { ValidType, ValidCount } from '@/enums/common'
const { common, user } = useStore()
const router = useRouter()
const emit = defineEmits(['refresh'])
// @ts-ignore
const defaultPrompt = t('views.application.prompt.defaultPrompt', {
data: '{data}',
question: '{question}'
})
const applicationFormRef = ref()
const loading = ref(false)
const dialogVisible = ref<boolean>(false)
const applicationForm = ref<ApplicationFormType>({
name: '',
desc: '',
model_id: '',
multiple_rounds_dialogue: false,
prologue: t('views.application.prompt.defaultPrologue'),
dataset_id_list: [],
dataset_setting: {
top_n: 3,
similarity: 0.6,
max_paragraph_char_number: 5000,
search_mode: 'embedding',
no_references_setting: {
status: 'ai_questioning',
value: '{question}'
}
},
model_setting: {
prompt: defaultPrompt
},
problem_optimization: false,
type: 'SIMPLE'
})
const rules = reactive<FormRules<ApplicationFormType>>({
name: [
{
required: true,
message: t('views.application.applicationForm.form.appName.placeholder'),
trigger: 'blur'
}
]
})
watch(dialogVisible, (bool) => {
if (!bool) {
applicationForm.value = {
name: '',
desc: '',
model_id: '',
multiple_rounds_dialogue: false,
prologue: t('views.application.prompt.defaultPrologue'),
dataset_id_list: [],
dataset_setting: {
top_n: 3,
similarity: 0.6,
max_paragraph_char_number: 5000,
search_mode: 'embedding',
no_references_setting: {
status: 'ai_questioning',
value: '{question}'
}
},
model_setting: {
prompt: defaultPrompt
},
problem_optimization: false,
type: 'SIMPLE'
}
applicationFormRef.value?.clearValidate()
}
})
const open = (data: any) => {
delete data['id']
applicationForm.value = cloneDeep(data)
dialogVisible.value = true
}
const submitValid = (formEl: FormInstance | undefined) => {
if (user.isEnterprise()) {
submitHandle(formEl)
} else {
common
.asyncGetValid(ValidType.Application, ValidCount.Application, loading)
.then(async (res: any) => {
if (res?.data) {
submitHandle(formEl)
} else {
MsgAlert('提示', '社区版最多支持 5 个应用,如需拥有更多应用,请升级为专业版。')
}
})
}
}
const submitHandle = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid) => {
if (valid) {
applicationApi.postApplication(applicationForm.value, loading).then((res) => {
MsgSuccess(t('views.application.applicationForm.buttons.createSuccess'))
emit('refresh')
dialogVisible.value = false
})
}
})
}
defineExpose({ open })
</script>
<style lang="scss" scope></style>

View File

@ -89,15 +89,25 @@
</el-button>
</el-tooltip>
<el-divider direction="vertical" />
<el-tooltip
effect="dark"
:content="$t('views.application.applicationList.card.delete.tooltip')"
placement="top"
>
<el-button text @click.stop="deleteApplication(item)">
<el-icon><Delete /></el-icon>
</el-button>
</el-tooltip>
<span @click.stop>
<el-dropdown trigger="click">
<el-button text @click.stop>
<el-icon><MoreFilled /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="copyApplication(item)">
<AppIcon iconName="app-copy"></AppIcon>
复制</el-dropdown-item
>
<el-dropdown-item icon="Delete" @click.stop="deleteApplication(item)">{{
$t('views.application.applicationList.card.delete.tooltip')
}}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</span>
</div>
</template>
</CardBox>
@ -106,12 +116,14 @@
</InfiniteScroll>
</div>
<CreateApplicationDialog ref="CreateApplicationDialogRef" />
<CopyApplicationDialog ref="CopyApplicationDialogRef" @refresh="refresh" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from 'vue'
import applicationApi from '@/api/application'
import CreateApplicationDialog from './component/CreateApplicationDialog.vue'
import CopyApplicationDialog from './component/CopyApplicationDialog.vue'
import { MsgSuccess, MsgConfirm } from '@/utils/message'
import { isAppIcon } from '@/utils/application'
import { useRouter } from 'vue-router'
@ -121,6 +133,7 @@ import { t } from '@/locales'
const { application } = useStore()
const router = useRouter()
const CopyApplicationDialogRef = ref()
const CreateApplicationDialogRef = ref()
const loading = ref(false)
@ -134,6 +147,10 @@ const paginationConfig = reactive({
const searchValue = ref('')
function copyApplication(row: any) {
CopyApplicationDialogRef.value.open(row)
}
function settingApplication(row: any) {
if (isWorkFlow(row.type)) {
router.push({ path: `/application/${row.id}/workflow` })
@ -188,13 +205,16 @@ function getList() {
})
}
function refresh() {
paginationConfig.total = 0
paginationConfig.current_page = 1
applicationList.value = []
getList()
}
onMounted(() => {
console.log(router)
getList()
})
</script>
<style lang="scss" scoped>
.application-card {