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

View File

@ -28,7 +28,8 @@ export default {
title: { title: {
create: '创建应用', create: '创建应用',
edit: '设置', edit: '设置',
info: '应用信息' info: '应用信息',
copy: '复制应用'
}, },
form: { form: {
appName: { appName: {
@ -70,7 +71,9 @@ export default {
create: '创建', create: '创建',
createSuccess: '创建成功', createSuccess: '创建成功',
save: '保存', save: '保存',
saveSuccess: '保存成功' saveSuccess: '保存成功',
copy: '复制',
copySuccess: '复制成功'
}, },
dialogues: { dialogues: {
addDataset: '添加关联知识库', 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-button>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" /> <el-divider direction="vertical" />
<el-tooltip <span @click.stop>
effect="dark" <el-dropdown trigger="click">
:content="$t('views.application.applicationList.card.delete.tooltip')" <el-button text @click.stop>
placement="top" <el-icon><MoreFilled /></el-icon>
> </el-button>
<el-button text @click.stop="deleteApplication(item)"> <template #dropdown>
<el-icon><Delete /></el-icon> <el-dropdown-menu>
</el-button> <el-dropdown-item @click="copyApplication(item)">
</el-tooltip> <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> </div>
</template> </template>
</CardBox> </CardBox>
@ -106,12 +116,14 @@
</InfiniteScroll> </InfiniteScroll>
</div> </div>
<CreateApplicationDialog ref="CreateApplicationDialogRef" /> <CreateApplicationDialog ref="CreateApplicationDialogRef" />
<CopyApplicationDialog ref="CopyApplicationDialogRef" @refresh="refresh" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, reactive } from 'vue' import { ref, onMounted, reactive } from 'vue'
import applicationApi from '@/api/application' import applicationApi from '@/api/application'
import CreateApplicationDialog from './component/CreateApplicationDialog.vue' import CreateApplicationDialog from './component/CreateApplicationDialog.vue'
import CopyApplicationDialog from './component/CopyApplicationDialog.vue'
import { MsgSuccess, MsgConfirm } from '@/utils/message' import { MsgSuccess, MsgConfirm } from '@/utils/message'
import { isAppIcon } from '@/utils/application' import { isAppIcon } from '@/utils/application'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
@ -121,6 +133,7 @@ import { t } from '@/locales'
const { application } = useStore() const { application } = useStore()
const router = useRouter() const router = useRouter()
const CopyApplicationDialogRef = ref()
const CreateApplicationDialogRef = ref() const CreateApplicationDialogRef = ref()
const loading = ref(false) const loading = ref(false)
@ -134,6 +147,10 @@ const paginationConfig = reactive({
const searchValue = ref('') const searchValue = ref('')
function copyApplication(row: any) {
CopyApplicationDialogRef.value.open(row)
}
function settingApplication(row: any) { function settingApplication(row: any) {
if (isWorkFlow(row.type)) { if (isWorkFlow(row.type)) {
router.push({ path: `/application/${row.id}/workflow` }) 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(() => { onMounted(() => {
console.log(router)
getList() getList()
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.application-card { .application-card {