feat: model

This commit is contained in:
wangdan-fit2cloud 2025-06-24 17:44:51 +08:00
parent 275ec80701
commit 1dab1ebc47
18 changed files with 188 additions and 2397 deletions

View File

@ -144,7 +144,7 @@
@load="getList"
:loading="loading"
>
<el-row v-if="applicationList.length > 0" :gutter="15">
<el-row v-if="applicationList.length > 0" :gutter="15" class="w-full">
<template v-for="(item, index) in applicationList" :key="index">
<el-col
v-if="item.resource_type === 'folder'"

View File

@ -236,9 +236,9 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
import type { Provider, BaseModel } from '@/api/type/model'
import type { Dict, KeyValue } from '@/api/type/common'
import ModelApi from '@/api/model/model'
import ProviderApi from '@/api/model/provider'
import type { FormField } from '@/components/dynamics-form/type'
import DynamicsForm from '@/components/dynamics-form/index.vue'
@ -248,7 +248,19 @@ import { PermissionType, PermissionDesc } from '@/enums/model'
import { input_type_list } from '@/components/dynamics-form/constructor/data'
import AddParamDrawer from '@/views/model/component/AddParamDrawer.vue'
import { t } from '@/locales'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
const route = useRoute()
const type = computed(() => {
if (route.path.includes('shared')) {
return 'systemShare'
} else if (route.path.includes('resource-management')) {
return 'systemManage'
} else {
return 'workspace'
}
})
const providerValue = ref<Provider>()
const dynamicsFormRef = ref<InstanceType<typeof DynamicsForm>>()
const emit = defineEmits(['change', 'submit'])
@ -378,18 +390,20 @@ const submit = () => {
?.validate()
.then(() => {
if (providerValue.value) {
ModelApi.createModel(
{
...base_form_data.value,
credential: credential_form_data.value,
provider: providerValue.value.provider,
},
loading,
).then((ok) => {
close()
MsgSuccess(t('views.model.tip.createSuccessMessage'))
emit('submit')
})
loadSharedApi({ type: 'model', systemType: type.value })
.createModel(
{
...base_form_data.value,
credential: credential_form_data.value,
provider: providerValue.value.provider,
},
loading,
)
.then((ok: any) => {
close()
MsgSuccess(t('views.model.tip.createSuccessMessage'))
emit('submit')
})
}
})
.catch(() => {

View File

@ -10,7 +10,7 @@
<template #header="{ close, titleId, titleClass }">
<el-breadcrumb separator=">">
<el-breadcrumb-item
><span class="active-breadcrumb">{{
><span class="active-breadcrumb">{{
`${$t('common.edit')} ${providerValue?.name}`
}}</span></el-breadcrumb-item
>
@ -74,8 +74,8 @@
<div class="mr-4">
<span>{{ $t('views.model.modelForm.base_model.label') }} </span>
<span class="danger ml-4">{{
$t('views.model.modelForm.base_model.tooltip')
}}</span>
$t('views.model.modelForm.base_model.tooltip')
}}</span>
</div>
</div>
</template>
@ -119,17 +119,30 @@
</el-dialog>
</template>
<script setup lang="ts">
import {ref, computed} from 'vue'
import type {Provider, BaseModel, Model} from '@/api/type/model'
import type {Dict, KeyValue} from '@/api/type/common'
import ModelApi from '@/api/model/model'
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
import type { Provider, BaseModel, Model } from '@/api/type/model'
import type { Dict, KeyValue } from '@/api/type/common'
import ProviderApi from '@/api/model/provider'
import type {FormField} from '@/components/dynamics-form/type'
import type { FormField } from '@/components/dynamics-form/type'
import DynamicsForm from '@/components/dynamics-form/index.vue'
import type {FormRules} from 'element-plus'
import {MsgSuccess} from '@/utils/message'
import {PermissionType, PermissionDesc} from '@/enums/model'
import {t} from '@/locales'
import type { FormRules } from 'element-plus'
import { MsgSuccess } from '@/utils/message'
import { PermissionType, PermissionDesc } from '@/enums/model'
import { t } from '@/locales'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
const route = useRoute()
const type = computed(() => {
if (route.path.includes('shared')) {
return 'systemShare'
} else if (route.path.includes('resource-management')) {
return 'systemManage'
} else {
return 'workspace'
}
})
const providerValue = ref<Provider>()
const dynamicsFormRef = ref<InstanceType<typeof DynamicsForm>>()
@ -167,13 +180,13 @@ const base_form_data = ref<{
model_type: string
model_name: string
}>({name: '', model_type: '', model_name: ''})
}>({ name: '', model_type: '', model_name: '' })
const credential_form_data = ref<Dict<any>>({})
const form_data = computed({
get: () => {
return {...credential_form_data.value, ...base_form_data.value}
return { ...credential_form_data.value, ...base_form_data.value }
},
set: (event: any) => {
credential_form_data.value = event
@ -209,27 +222,29 @@ const list_base_model = (model_type: any, change?: boolean) => {
}
const open = (provider: Provider, model: Model) => {
modelValue.value = model
ModelApi.getModelById(model.id, formLoading).then((ok) => {
modelValue.value = ok.data
ProviderApi.listModelType(model.provider, model_type_loading).then((ok) => {
model_type_list.value = ok.data
list_base_model(model.model_type)
})
providerValue.value = provider
loadSharedApi({ type: 'model', systemType: type.value })
.getModelById(model.id, formLoading)
.then((ok: any) => {
modelValue.value = ok.data
ProviderApi.listModelType(model.provider, model_type_loading).then((ok) => {
model_type_list.value = ok.data
list_base_model(model.model_type)
})
providerValue.value = provider
base_form_data.value = {
name: model.name,
model_type: model.model_type,
model_name: model.model_name,
}
form_data.value = model.credential
getModelForm(model.model_name)
})
base_form_data.value = {
name: model.name,
model_type: model.model_type,
model_name: model.model_name,
}
form_data.value = model.credential
getModelForm(model.model_name)
})
dialogVisible.value = true
}
const close = () => {
base_form_data.value = {name: '', model_type: '', model_name: ''}
base_form_data.value = { name: '', model_type: '', model_name: '' }
dynamicsFormRef.value?.ruleFormRef?.resetFields()
credential_form_data.value = {}
model_form_field.value = []
@ -240,23 +255,25 @@ const close = () => {
const submit = () => {
dynamicsFormRef.value?.validate().then(() => {
if (modelValue.value) {
ModelApi.updateModel(
modelValue.value.id,
{
...base_form_data.value,
credential: credential_form_data.value,
},
loading,
).then((ok) => {
MsgSuccess(t('views.model.tip.updateSuccessMessage'))
close()
emit('submit')
})
loadSharedApi({ type: 'model', systemType: type.value })
.updateModel(
modelValue.value.id,
{
...base_form_data.value,
credential: credential_form_data.value,
},
loading,
)
.then((ok: any) => {
MsgSuccess(t('views.model.tip.updateSuccessMessage'))
close()
emit('submit')
})
}
})
}
defineExpose({open, close})
defineExpose({ open, close })
</script>
<style lang="scss" scoped>
.select-provider {

View File

@ -28,7 +28,7 @@
</el-text>
</template>
<template #tag>
<el-tag v-if="isShared" type="info" class="info-tag">
<el-tag v-if="isShared || isSystemShare" type="info" class="info-tag">
{{ t('views.system.shared.label') }}
</el-tag>
</template>
@ -85,6 +85,12 @@
>
{{ $t('common.modify') }}
</el-dropdown-item>
<el-dropdown-item
v-if="isSystemShare"
icon="Lock"
@click.stop="openAuthorizedWorkspaceDialog(model)"
>{{ $t('views.system.shared.authorized_workspace') }}</el-dropdown-item
>
<el-dropdown-item
v-if="
@ -93,7 +99,6 @@
currentModel.model_type === 'IMAGE' ||
currentModel.model_type === 'TTI' ||
permissionPrecise.paramSetting()
"
:disabled="!is_permisstion"
icon="Setting"
@ -107,9 +112,7 @@
:disabled="!is_permisstion"
text
@click.stop="deleteModel"
v-if="
permissionPrecise.delete()
"
v-if="permissionPrecise.delete()"
>
{{ $t('common.delete') }}
</el-dropdown-item>
@ -119,11 +122,14 @@
</template>
<EditModel ref="editModelRef" @submit="emit('change')"></EditModel>
<ParamSettingDialog ref="paramSettingRef" :model="model" />
<AuthorizedWorkspace
ref="AuthorizedWorkspaceDialogRef"
v-if="isSystemShare"
></AuthorizedWorkspace>
</card-box>
</template>
<script setup lang="ts">
import type { Provider, Model } from '@/api/type/model'
import ModelApi from '@/api/model/model'
import { computed, ref, onMounted, onBeforeUnmount } from 'vue'
import EditModel from '@/views/model/component/EditModel.vue'
// import DownloadLoading from '@/components/loading/DownloadLoading.vue'
@ -131,36 +137,28 @@ import { MsgConfirm } from '@/utils/message'
import { modelType } from '@/enums/model'
import useStore from '@/stores'
import ParamSettingDialog from './ParamSettingDialog.vue'
import AuthorizedWorkspace from '@/views/system-shared/AuthorizedWorkspaceDialog.vue'
import { t } from '@/locales'
import { PermissionConst, RoleConst } from '@/utils/permission/data'
import { hasPermission } from '@/utils/permission'
import { useRoute } from 'vue-router'
import permissionMap from '@/permission'
const route = useRoute()
const type = computed(() => {
if (route.path.includes('shared')) {
return 'systemShare'
} else if (route.path.includes('resource-management')) {
return 'systemManage'
} else {
return 'workspace'
}
})
const permissionPrecise = computed(() => {
return permissionMap['model'][type.value]
})
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
const props = defineProps<{
model: Model
provider_list: Array<Provider>
updateModelById: (model_id: string, model: Model) => void
isShared?: boolean | undefined
isSystemShare?: boolean | undefined
sharedType: 'systemShare' | 'workspace' | 'systemManage'
}>()
const { user } = useStore()
const permissionPrecise = computed(() => {
return permissionMap['model'][props.sharedType]
})
const downModel = ref<Model>()
const is_permisstion = computed(() => {
@ -196,18 +194,22 @@ const deleteModel = () => {
},
)
.then(() => {
ModelApi.deleteModel(props.model.id).then(() => {
emit('change')
})
loadSharedApi({ type: 'model', systemType: props.sharedType })
.deleteModel(props.model.id)
.then(() => {
emit('change')
})
})
.catch(() => {})
}
const cancelDownload = () => {
ModelApi.pauseDownload(props.model.id).then(() => {
downModel.value = undefined
emit('change')
})
loadSharedApi({ type: 'model', systemType: type.value })
.pauseDownload(props.model.id)
.then(() => {
downModel.value = undefined
emit('change')
})
}
const openEditModel = () => {
const provider = props.provider_list.find((p) => p.provider === props.model.provider)
@ -225,9 +227,11 @@ const icon = computed(() => {
const initInterval = () => {
interval = setInterval(() => {
if (currentModel.value.status === 'DOWNLOAD') {
ModelApi.getModelMetaById(props.model.id).then((ok) => {
downModel.value = ok.data
})
loadSharedApi({ type: 'model', systemType: type.value })
.getModelMetaById(props.model.id)
.then((ok: any) => {
downModel.value = ok.data
})
} else {
if (downModel.value) {
props.updateModelById(props.model.id, downModel.value)
@ -251,6 +255,13 @@ const openParamSetting = () => {
paramSettingRef.value?.open()
}
const AuthorizedWorkspaceDialogRef = ref()
function openAuthorizedWorkspaceDialog(row: any) {
if (AuthorizedWorkspaceDialogRef.value) {
AuthorizedWorkspaceDialogRef.value.open(row, 'Model')
}
}
onMounted(() => {
initInterval()
})

View File

@ -81,17 +81,29 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
import type { Model } from '@/api/type/model'
import { ref } from 'vue'
import AddParamDrawer from './AddParamDrawer.vue'
import { MsgError, MsgSuccess } from '@/utils/message'
import ModelApi from '@/api/model/model'
import { input_type_list } from '@/components/dynamics-form/constructor/data'
import { t } from '@/locales'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
const props = defineProps<{
model: Model
}>()
const route = useRoute()
const type = computed(() => {
if (route.path.includes('shared')) {
return 'systemShare'
} else if (route.path.includes('resource-management')) {
return 'systemManage'
} else {
return 'workspace'
}
})
const loading = ref<boolean>(false)
const dialogVisible = ref<boolean>(false)
const modelParamsForm = ref<any[]>([])
@ -100,8 +112,9 @@ const AddParamRef = ref()
const open = () => {
dialogVisible.value = true
loading.value = true
ModelApi.getModelParamsForm(props.model.id, loading)
.then((ok) => {
loadSharedApi({ type: 'model', systemType: type.value })
.getModelParamsForm(props.model.id, loading)
.then((ok: any) => {
loading.value = false
modelParamsForm.value = ok.data
})
@ -151,13 +164,13 @@ function refresh(data: any, index: any) {
}
function submit() {
ModelApi.updateModelParamsForm(props.model.id, modelParamsForm.value, loading).then(
(ok) => {
loadSharedApi({ type: 'model', systemType: type.value })
.updateModelParamsForm(props.model.id, modelParamsForm.value, loading)
.then((ok: any) => {
MsgSuccess(t('views.model.tip.saveSuccessMessage'))
close()
// emit('submit')
},
)
})
}
defineExpose({ open, close })

View File

@ -75,8 +75,8 @@
:xs="24"
:sm="12"
:md="12"
:lg="8"
:xl="6"
:lg="isSystemShare ? 12 : 8"
:xl="isSystemShare ? 12 : 8"
class="mb-16"
v-for="(model, i) in row"
:key="i"
@ -87,6 +87,8 @@
:model="model"
:provider_list="provider_list"
:isShared="isShared"
:isSystemShare="isSystemShare"
:sharedType="type"
>
</ModelCard>
</el-col>
@ -125,11 +127,9 @@ import { t } from '@/locales'
import { PermissionConst, RoleConst } from '@/utils/permission/data'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
import { useRoute } from 'vue-router'
import useStore from '@/stores'
import permissionMap from '@/permission'
const route = useRoute()
const { folder, user } = useStore()
const type = computed(() => {
if (route.path.includes('shared')) {
@ -143,7 +143,9 @@ const type = computed(() => {
const permissionPrecise = computed(() => {
return permissionMap['model'][type.value]
})
const isSystemShare = computed(() => {
return type.value === 'systemShare'
})
const commonList1 = ref()
const commonList2 = ref()
const loading = ref<boolean>(false)
@ -200,7 +202,7 @@ const openCreateModel = (provider?: Provider, model_type?: string) => {
const list_model = () => {
const params = active_provider.value?.provider ? { provider: active_provider.value.provider } : {}
loadSharedApi({ type: 'model', isShared: isShared.value })
loadSharedApi({ type: 'model', isShared: isShared.value, systemType: type.value })
.getModel({ ...model_search_form.value, ...params }, list_model_loading)
.then((ok: any) => {
model_list.value = ok.data

View File

@ -1,229 +0,0 @@
<template>
<div class="model-shared">
<ContentContainer
:header="t('views.system.shared.shared_model')"
v-loading="list_model_loading"
>
<template #search>
<div class="flex">
<div class="flex-between complex-search">
<el-select
class="complex-search__left"
v-model="search_type"
style="width: 120px"
@change="search_type_change"
>
<el-option :label="$t('common.creator')" value="create_user" />
<el-option
:label="$t('views.model.modelForm.model_type.label')"
value="model_type"
/>
<el-option :label="$t('views.model.modelForm.modeName.label')" value="name" />
</el-select>
<el-input
v-if="search_type === 'name'"
v-model="model_search_form.name"
@change="list_model"
:placeholder="$t('common.searchBar.placeholder')"
style="width: 220px"
clearable
/>
<el-select
v-else-if="search_type === 'create_user'"
v-model="model_search_form.create_user"
@change="list_model"
clearable
style="width: 220px"
>
<el-option
v-for="u in user_options"
:key="u.id"
:value="u.id"
:label="u.username"
/>
</el-select>
<el-select
v-else-if="search_type === 'model_type'"
v-model="model_search_form.model_type"
clearable
@change="list_model"
style="width: 220px"
>
<template v-for="item in modelTypeList" :key="item.value">
<el-option :label="item.text" :value="item.value" />
</template>
</el-select>
</div>
</div>
</template>
<div class="model-list-height">
<el-scrollbar>
<el-row v-if="model_split_list.length > 0" :gutter="15" class="w-full">
<template v-for="(row, index) in model_split_list" :key="index">
<el-col
:xs="24"
:sm="12"
:md="12"
:lg="8"
:xl="6"
class="mb-16"
v-for="(model, i) in row"
:key="i"
>
<ModelCard
@change="list_model"
:updateModelById="updateModelById"
:model="model"
:provider_list="provider_list"
>
</ModelCard>
</el-col>
</template>
</el-row>
<el-empty :description="$t('common.noData')" v-else />
</el-scrollbar>
</div>
</ContentContainer>
<CreateModelDialog
ref="createModelRef"
@submit="list_model"
@change="openCreateModel($event)"
></CreateModelDialog>
<SelectProviderDialog
ref="selectProviderRef"
@change="(provider, modelType) => openCreateModel(provider, modelType)"
></SelectProviderDialog>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, computed } from 'vue'
import ProviderApi from '@/api/model/provider'
import ModelApi from '@/api/system-shared/model'
import ModelWorkspaceApi from '@/api/shared-workspace'
import type { Provider, Model } from '@/api/type/model'
import ModelCard from '@/views/shared/model-shared/component/ModelCardSharedWorkspace.vue'
import ProviderComponent from '@/views/shared/model-shared/component/Provider.vue'
import { splitArray } from '@/utils/common'
import { modelTypeList, allObj } from '@/views/shared/model-shared/component/data'
import CreateModelDialog from '@/views/shared/model-shared/component/CreateModelDialog.vue'
import iconMap from '@/components/app-icon/icons/common'
import SelectProviderDialog from '@/views/shared/model-shared/component/SelectProviderDialog.vue'
import useStore from '@/stores/modules-shared-system'
import { t } from '@/locales'
const { model } = useStore()
const rightOutlined = iconMap['right-outlined'].iconReader()
const commonList1 = ref()
const commonList2 = ref()
const loading = ref<boolean>(false)
const active_provider = ref<Provider>()
const search_type = ref('name')
const model_search_form = ref<{
name: string
create_user: string
model_type: string
}>({
name: '',
create_user: '',
model_type: '',
})
const user_options = ref<any[]>([])
const list_model_loading = ref<boolean>(false)
const provider_list = ref<Array<Provider>>([])
const model_list = ref<Array<Model>>([])
const updateModelById = (model_id: string, model: Model) => {
model_list.value
.filter((m) => m.id == model_id)
.forEach((m) => {
m.status = model.status
})
}
const model_split_list = computed(() => {
return splitArray(model_list.value, 2)
})
const createModelRef = ref<InstanceType<typeof CreateModelDialog>>()
const selectProviderRef = ref<InstanceType<typeof SelectProviderDialog>>()
const clickListHandle = (item: Provider) => {
active_provider.value = item
list_model()
if (active_provider.value.provider === '') {
commonList1.value.clearCurrent()
commonList2.value.clearCurrent()
}
}
const openCreateModel = (provider?: Provider, model_type?: string) => {
if (provider && provider.provider) {
createModelRef.value?.open(provider, model_type)
} else {
selectProviderRef.value?.open()
}
}
const list_model = () => {
const params = active_provider.value?.provider ? { provider: active_provider.value.provider } : {}
ModelWorkspaceApi
.getSharedWorkspaceModelPage({ ...model_search_form.value, ...params }, list_model_loading)
.then((ok: any) => {
model_list.value = ok.data
const v = model_list.value.map((m) => ({ id: m.user_id, username: m.username }))
if (user_options.value.length === 0) {
user_options.value = Array.from(new Map(v.map((item) => [item.id, item])).values())
}
})
}
const search_type_change = () => {
model_search_form.value = { name: '', create_user: '', model_type: '' }
}
onMounted(() => {
ProviderApi.getProvider(loading).then((ok) => {
active_provider.value = allObj
provider_list.value = [allObj, ...ok.data]
list_model()
})
})
</script>
<style lang="scss" scoped>
.model-shared {
height: 100%;
.shared-header {
color: #646a73;
font-weight: 400;
font-size: 14px;
line-height: 22px;
display: flex;
align-items: center;
margin-bottom: 21px;
:deep(.el-icon i) {
height: 12px;
}
.sub-title {
color: #1f2329;
}
}
.h-full {
border-radius: 8px;
box-shadow: 0px 2px 4px 0px #1f23291f;
background: #fff;
}
}
</style>

View File

@ -1,85 +0,0 @@
<template>
<el-drawer
v-model="drawer"
:direction="direction"
size="600"
:destroy-on-close="true"
:before-close="cancelClick"
>
<template #header>
<h4>
{{
isEdit
? $t('common.param.editParam')
: $t('common.param.addParam')
}}
</h4>
</template>
<template #default>
<DynamicsFormConstructor
v-model="currentItem"
label-position="top"
require-asterisk-position="right"
ref="DynamicsFormConstructorRef"
></DynamicsFormConstructor>
</template>
<template #footer>
<div style="flex: auto">
<el-button @click="cancelClick">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="confirmClick()">{{
isEdit ? $t('common.save') : $t('common.add')
}}</el-button>
</div>
</template>
</el-drawer>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DrawerProps } from 'element-plus'
import { cloneDeep } from 'lodash'
import DynamicsFormConstructor from '@/components/dynamics-form/constructor/index.vue'
const drawer = ref(false)
const direction = ref<DrawerProps['direction']>('rtl')
const isEdit = ref(false)
const DynamicsFormConstructorRef = ref<InstanceType<typeof DynamicsFormConstructor>>()
const currentItem = ref(null)
const currentIndex = ref(null)
const emit = defineEmits(['refresh'])
const open = (row: any, index: any) => {
if (row) {
currentItem.value = cloneDeep(row)
currentIndex.value = index
isEdit.value = true
}
drawer.value = true
}
function cancelClick() {
drawer.value = false
isEdit.value = false
currentItem.value = null
currentIndex.value = null
}
function confirmClick() {
const formEl = DynamicsFormConstructorRef.value
formEl?.validate().then((valid) => {
if (valid) {
emit('refresh', formEl?.getData(), currentIndex.value)
drawer.value = false
isEdit.value = false
currentItem.value = null
currentIndex.value = null
}
})
}
defineExpose({ open })
</script>
<style scoped lang="scss"></style>

View File

@ -1,462 +0,0 @@
<template>
<el-dialog
v-model="dialogVisible"
width="600px"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
:before-close="close"
append-to-body
>
<template #header="{ close, titleId, titleClass }">
<el-breadcrumb separator=">">
<el-breadcrumb-item>
<span @click="toSelectProvider" class="select-provider">
{{ $t('views.model.providerPlaceholder') }}
</span>
</el-breadcrumb-item>
<el-breadcrumb-item
><span class="active-breadcrumb">{{
`${$t('common.add')} ${providerValue?.name}`
}}</span></el-breadcrumb-item
>
</el-breadcrumb>
</template>
<el-tabs v-model="activeName">
<el-tab-pane :label="$t('views.model.modelForm.title.baseInfo')" name="base-info">
<DynamicsForm
v-model="form_data"
:render_data="model_form_field"
:model="form_data"
ref="dynamicsFormRef"
label-position="top"
require-asterisk-position="right"
class="mb-24"
label-width="auto"
>
<template #default>
<el-form-item prop="name" :rules="base_form_data_rule.name">
<template #label>
<div class="flex align-center" style="display: inline-flex">
<div class="mr-4">
<span> {{ $t('views.model.modelForm.modeName.label') }} </span>
</div>
<el-tooltip effect="dark" placement="right">
<template #content>
<p>{{ $t('views.model.modelForm.modeName.tooltip') }}</p>
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
</div>
</template>
<el-input
v-model="base_form_data.name"
maxlength="64"
show-word-limit
:placeholder="$t('views.model.modelForm.modeName.placeholder')"
/>
</el-form-item>
<el-form-item prop="model_type" :rules="base_form_data_rule.model_type">
<template #label>
<div class="flex align-center" style="display: inline-flex">
<span class="mr-4">{{ $t('views.model.modelForm.model_type.label') }} </span>
<el-tooltip effect="dark" placement="right">
<template #content>
<p>{{ $t('views.model.modelForm.model_type.tooltip1') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip2') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip3') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip4') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip5') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip6') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip7') }}</p>
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
</div>
</template>
<el-select
v-loading="model_type_loading"
@change="list_base_model($event, true)"
v-model="base_form_data.model_type"
class="w-full m-2"
:placeholder="$t('views.model.modelForm.model_type.placeholder')"
>
<el-option
v-for="item in model_type_list"
:key="item.value"
:label="item.key"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="model_name" :rules="base_form_data_rule.model_name">
<template #label>
<div class="flex align-center" style="display: inline-flex">
<div class="mr-4">
<span>{{ $t('views.model.modelForm.base_model.label') }} </span>
<span class="danger ml-4">{{
$t('views.model.modelForm.base_model.tooltip')
}}</span>
</div>
</div>
</template>
<el-select
@change="getModelForm($event)"
v-loading="base_model_loading"
v-model="base_form_data.model_name"
class="w-full m-2"
:placeholder="$t('views.model.modelForm.base_model.placeholder')"
filterable
allow-create
default-first-option
>
<el-option v-for="item in base_model_list" :key="item.name" :value="item.name">
<template #default>
<div class="flex align-center" style="display: inline-flex">
<div class="flex-between mr-4">
<span>{{ item.name }} </span>
</div>
<el-tooltip effect="dark" placement="right" v-if="item.desc">
<template #content>
<p class="w-280">{{ item.desc }}</p>
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
</div>
</template>
</el-option>
</el-select>
</el-form-item>
</template>
</DynamicsForm>
</el-tab-pane>
<el-tab-pane :label="$t('views.model.modelForm.title.advancedInfo')" name="advanced-info">
<el-empty
v-if="!base_form_data.model_type || !base_form_data.model_name"
:description="$t('views.model.tip.emptyMessage1')"
/>
<el-empty
v-else-if="
base_form_data.model_type === 'RERANKER' ||
base_form_data.model_type === 'EMBEDDING' ||
base_form_data.model_type === 'STT'
"
:description="$t('views.model.tip.emptyMessage2')"
/>
<div class="flex-between mb-8" v-else>
<h5>{{ $t('views.model.modelForm.title.modelParams') }}</h5>
<el-button
type="text"
@click.stop="openAddDrawer()"
:disabled="
base_form_data.model_type !== 'TTS' &&
base_form_data.model_type !== 'LLM' &&
base_form_data.model_type !== 'IMAGE' &&
base_form_data.model_type !== 'TTI'
"
>
<AppIcon iconName="Plus" class="add-icon" />{{ $t('common.add') }}
</el-button>
</div>
<el-table
:data="base_form_data.model_params_form"
v-if="base_form_data.model_params_form?.length > 0"
class="mb-16"
>
<el-table-column
prop="label"
:label="$t('dynamicsForm.paramForm.name.label')"
show-overflow-tooltip
>
<template #default="{ row }">
<span v-if="row.label && row.label.input_type === 'TooltipLabel'">{{
row.label.label
}}</span>
<span v-else>{{ row.label }}</span>
</template>
</el-table-column>
<el-table-column
prop="field"
:label="$t('dynamicsForm.paramForm.field.label')"
show-overflow-tooltip
width="95px"
/>
<el-table-column :label="$t('dynamicsForm.paramForm.input_type.label')" width="110px">
<template #default="{ row }">
<el-tag type="info" class="info-tag">{{
input_type_list.find((item) => item.value === row.input_type)?.label
}}</el-tag>
</template>
</el-table-column>
<el-table-column
prop="default_value"
:label="$t('dynamicsForm.default.label')"
show-overflow-tooltip
/>
<el-table-column :label="$t('common.required')">
<template #default="{ row }">
<div @click.stop>
<el-switch disabled size="small" v-model="row.required" />
</div>
</template>
</el-table-column>
<el-table-column :label="$t('common.operation')" align="left" width="90">
<template #default="{ row, $index }">
<span class="mr-4">
<el-tooltip effect="dark" :content="$t('common.modify')" placement="top">
<el-button type="primary" text @click.stop="openAddDrawer(row, $index)">
<el-icon><EditPen /></el-icon>
</el-button>
</el-tooltip>
</span>
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
<el-button type="primary" text @click="deleteParam($index)">
<el-icon>
<Delete />
</el-icon>
</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<template #footer>
<span class="dialog-footer">
<el-button @click="close">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submit" :loading="loading">
{{ $t('common.save') }}
</el-button>
</span>
</template>
</el-dialog>
<AddParamDrawer ref="AddParamRef" @refresh="refresh" />
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { Provider, BaseModel } from '@/api/type/model'
import type { Dict, KeyValue } from '@/api/type/common'
import ModelApi from '@/api/system-shared/model'
import ProviderApi from '@/api/model/provider'
import type { FormField } from '@/components/dynamics-form/type'
import DynamicsForm from '@/components/dynamics-form/index.vue'
import type { FormRules } from 'element-plus'
import { MsgError, MsgSuccess, MsgWarning } from '@/utils/message'
import { PermissionType, PermissionDesc } from '@/enums/model'
import { input_type_list } from '@/components/dynamics-form/constructor/data'
import AddParamDrawer from '@/views/shared/model-shared/component/AddParamDrawer.vue'
import { t } from '@/locales'
const providerValue = ref<Provider>()
const dynamicsFormRef = ref<InstanceType<typeof DynamicsForm>>()
const emit = defineEmits(['change', 'submit'])
const loading = ref<boolean>(false)
const model_type_loading = ref<boolean>(false)
const base_model_loading = ref<boolean>(false)
const model_type_list = ref<Array<KeyValue<string, string>>>([])
const base_model_list = ref<Array<BaseModel>>()
const model_form_field = ref<Array<FormField>>([])
const dialogVisible = ref<boolean>(false)
const activeName = ref('base-info')
const AddParamRef = ref()
const base_form_data_rule = ref<FormRules>({
name: {
required: true,
trigger: 'blur',
message: t('views.model.modelForm.modeName.requiredMessage'),
},
model_type: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.model_type.requiredMessage'),
},
model_name: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.base_model.requiredMessage'),
},
})
const base_form_data = ref<{
name: string
model_type: string
model_name: string
model_params_form: any
}>({ name: '', model_type: '', model_name: '', model_params_form: [] })
const credential_form_data = ref<Dict<any>>({})
const form_data = computed({
get: () => {
return {
...credential_form_data.value,
name: base_form_data.value.name,
model_type: base_form_data.value.model_type,
model_name: base_form_data.value.model_name,
model_params_form: base_form_data.value.model_params_form,
}
},
set: (event: any) => {
credential_form_data.value = event
},
})
const getModelForm = (model_name: string) => {
if (!form_data.value.model_type) {
MsgWarning(t('views.model.modelForm.model_type.requiredMessage'))
base_form_data.value.model_name = ''
return
}
if (providerValue.value) {
ProviderApi.getModelCreateForm(
providerValue.value.provider,
form_data.value.model_type,
model_name,
).then((ok) => {
model_form_field.value = ok.data
//
dynamicsFormRef.value?.render(model_form_field.value, undefined)
})
ProviderApi.listBaseModelParamsForm(
providerValue.value.provider,
form_data.value.model_type,
model_name,
base_model_loading,
).then((ok) => {
base_form_data.value.model_params_form = ok.data
})
}
}
const open = (provider: Provider, model_type?: string) => {
ProviderApi.listModelType(provider.provider, model_type_loading).then((ok) => {
model_type_list.value = ok.data
})
providerValue.value = provider
dialogVisible.value = true
base_form_data.value.model_type = model_type || ''
activeName.value = 'base-info'
if (model_type) {
list_base_model(model_type)
}
}
const list_base_model = (model_type: any, change?: boolean) => {
if (change) {
base_form_data.value.model_name = ''
base_form_data.value.model_params_form = []
}
if (providerValue.value) {
ProviderApi.listBaseModel(providerValue.value.provider, model_type, base_model_loading).then(
(ok) => {
base_model_list.value = ok.data
},
)
}
}
const close = () => {
base_form_data.value = {
name: '',
model_type: '',
model_name: '',
model_params_form: [],
}
credential_form_data.value = {}
model_form_field.value = []
base_model_list.value = []
loading.value = false
dialogVisible.value = false
}
const submit = () => {
dynamicsFormRef.value
?.validate()
.then(() => {
if (providerValue.value) {
ModelApi.createModel(
{
...base_form_data.value,
credential: credential_form_data.value,
provider: providerValue.value.provider,
},
loading,
).then((ok) => {
close()
MsgSuccess(t('views.model.tip.createSuccessMessage'))
emit('submit')
})
}
})
.catch(() => {
MsgError(t('views.model.tip.createErrorMessage'))
})
}
function openAddDrawer(data?: any, index?: any) {
AddParamRef.value?.open(data, index)
}
function deleteParam(index: any) {
base_form_data.value.model_params_form.splice(index, 1)
}
function refresh(data: any, index: any) {
for (let i = 0; i < base_form_data.value.model_params_form.length; i++) {
const field = base_form_data.value.model_params_form[i].field
let label = base_form_data.value.model_params_form[i].label
if (label && label.input_type === 'TooltipLabel') {
label = label.label
}
let label2 = data.label
if (label2 && label2.input_type === 'TooltipLabel') {
label2 = label2.label
}
if (field === data.field && index !== i) {
MsgError(t('views.model.tip.errorMessage') + data.field)
return
}
if (label === label2 && index !== i) {
MsgError(t('views.model.tip.errorMessage') + label)
return
}
}
if (index !== null) {
base_form_data.value.model_params_form.splice(index, 1, data)
} else {
base_form_data.value.model_params_form.push(data)
}
}
const toSelectProvider = () => {
close()
emit('change')
}
defineExpose({ open, close })
</script>
<style lang="scss" scoped>
.select-provider {
font-size: 16px;
color: rgba(100, 106, 115, 1);
font-weight: 400;
line-height: 24px;
cursor: pointer;
&:hover {
color: var(--el-color-primary);
}
}
.active-breadcrumb {
font-size: 16px;
color: rgba(31, 35, 41, 1);
font-weight: 500;
line-height: 24px;
}
</style>

View File

@ -1,280 +0,0 @@
<template>
<el-dialog
v-model="dialogVisible"
width="600px"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
:before-close="close"
>
<template #header="{ close, titleId, titleClass }">
<el-breadcrumb separator=">">
<el-breadcrumb-item
><span class="active-breadcrumb">{{
`${$t('common.edit')} ${providerValue?.name}`
}}</span></el-breadcrumb-item
>
</el-breadcrumb>
</template>
<DynamicsForm
v-loading="formLoading"
v-model="form_data"
:render_data="model_form_field"
:model="form_data"
ref="dynamicsFormRef"
label-position="top"
require-asterisk-position="right"
>
<template #default>
<el-form-item prop="name" :rules="base_form_data_rule.name">
<template #label>
<div class="flex align-center" style="display: inline-flex">
<div class="mr-4">
<span>{{ $t('views.model.modelForm.modeName.label') }} </span>
</div>
<el-tooltip effect="dark" placement="right">
<template #content>
<p>{{ $t('views.model.modelForm.modeName.tooltip') }}</p>
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
</div>
</template>
<el-input
v-model="base_form_data.name"
maxlength="64"
show-word-limit
:placeholder="$t('views.model.modelForm.modeName.placeholder')"
/>
</el-form-item>
<el-form-item prop="model_type" :rules="base_form_data_rule.model_type">
<template #label>
<span>{{ $t('views.model.modelForm.model_type.label') }}</span>
</template>
<el-select
disabled
v-loading="model_type_loading"
@change="list_base_model($event, true)"
v-model="base_form_data.model_type"
class="w-full m-2"
:placeholder="$t('views.model.modelForm.model_type.placeholder')"
>
<el-option
v-for="item in model_type_list"
:key="item.value"
:label="item.key"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="model_name" :rules="base_form_data_rule.model_name">
<template #label>
<div class="flex align-center" style="display: inline-flex">
<div class="mr-4">
<span>{{ $t('views.model.modelForm.base_model.label') }} </span>
<span class="danger ml-4">{{
$t('views.model.modelForm.base_model.tooltip')
}}</span>
</div>
</div>
</template>
<el-select
@change="getModelForm($event)"
v-loading="base_model_loading"
v-model="base_form_data.model_name"
class="w-full m-2"
:placeholder="$t('views.model.modelForm.base_model.requiredMessage')"
filterable
allow-create
default-first-option
>
<el-option v-for="item in base_model_list" :key="item.name" :value="item.name">
<template #default>
<div class="flex align-center" style="display: inline-flex">
<div class="flex-between mr-4">
<span>{{ item.name }} </span>
</div>
<el-tooltip effect="dark" placement="right" v-if="item.desc">
<template #content>
<p>{{ item.desc }}</p>
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
</div>
</template>
</el-option>
</el-select>
</el-form-item>
</template>
</DynamicsForm>
<template #footer>
<span class="dialog-footer">
<el-button @click="close">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submit" :loading="loading">
{{ $t('common.modify') }}
</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import {ref, computed} from 'vue'
import type {Provider, BaseModel, Model} from '@/api/type/model'
import type {Dict, KeyValue} from '@/api/type/common'
import ModelApi from '@/api/system-shared/model'
import ProviderApi from '@/api/model/provider'
import type {FormField} from '@/components/dynamics-form/type'
import DynamicsForm from '@/components/dynamics-form/index.vue'
import type {FormRules} from 'element-plus'
import {MsgSuccess} from '@/utils/message'
import {PermissionType, PermissionDesc} from '@/enums/model'
import {t} from '@/locales'
const providerValue = ref<Provider>()
const dynamicsFormRef = ref<InstanceType<typeof DynamicsForm>>()
const emit = defineEmits(['change', 'submit'])
const loading = ref<boolean>(false)
const formLoading = ref<boolean>(false)
const model_type_loading = ref<boolean>(false)
const base_model_loading = ref<boolean>(false)
const model_type_list = ref<Array<KeyValue<string, string>>>([])
const modelValue = ref<Model>()
const base_model_list = ref<Array<BaseModel>>([])
const model_form_field = ref<Array<FormField>>([])
const dialogVisible = ref<boolean>(false)
const base_form_data_rule = ref<FormRules>({
name: {
required: true,
trigger: 'blur',
message: t('views.model.modelForm.modeName.requiredMessage'),
},
model_type: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.model_type.requiredMessage'),
},
model_name: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.base_model.requiredMessage'),
},
})
const base_form_data = ref<{
name: string
model_type: string
model_name: string
}>({name: '', model_type: '', model_name: ''})
const credential_form_data = ref<Dict<any>>({})
const form_data = computed({
get: () => {
return {...credential_form_data.value, ...base_form_data.value}
},
set: (event: any) => {
credential_form_data.value = event
},
})
const getModelForm = (model_name: string) => {
if (providerValue.value) {
ProviderApi.getModelCreateForm(
providerValue.value.provider,
form_data.value.model_type,
model_name,
).then((ok) => {
model_form_field.value = ok.data
if (modelValue.value) {
//
dynamicsFormRef.value?.render(model_form_field.value, modelValue.value.credential)
}
})
}
}
const list_base_model = (model_type: any, change?: boolean) => {
if (change) {
base_form_data.value.model_name = ''
}
if (providerValue.value) {
ProviderApi.listBaseModel(providerValue.value.provider, model_type, base_model_loading).then(
(ok) => {
base_model_list.value = ok.data
},
)
}
}
const open = (provider: Provider, model: Model) => {
modelValue.value = model
ModelApi.getModelById(model.id, formLoading).then((ok) => {
modelValue.value = ok.data
ProviderApi.listModelType(model.provider, model_type_loading).then((ok) => {
model_type_list.value = ok.data
list_base_model(model.model_type)
})
providerValue.value = provider
base_form_data.value = {
name: model.name,
model_type: model.model_type,
model_name: model.model_name,
}
form_data.value = model.credential
getModelForm(model.model_name)
})
dialogVisible.value = true
}
const close = () => {
base_form_data.value = {name: '', model_type: '', model_name: ''}
dynamicsFormRef.value?.ruleFormRef?.resetFields()
credential_form_data.value = {}
model_form_field.value = []
base_model_list.value = []
dialogVisible.value = false
}
const submit = () => {
dynamicsFormRef.value?.validate().then(() => {
if (modelValue.value) {
ModelApi.updateModel(
modelValue.value.id,
{
...base_form_data.value,
credential: credential_form_data.value,
},
loading,
).then((ok) => {
MsgSuccess(t('views.model.tip.updateSuccessMessage'))
close()
emit('submit')
})
}
})
}
defineExpose({open, close})
</script>
<style lang="scss" scoped>
.select-provider {
font-size: 16px;
color: rgba(100, 106, 115, 1);
font-weight: 400;
line-height: 24px;
cursor: pointer;
&:hover {
color: var(--el-color-primary);
}
}
.active-breadcrumb {
font-size: 16px;
color: rgba(31, 35, 41, 1);
font-weight: 500;
line-height: 24px;
}
</style>

View File

@ -1,297 +0,0 @@
<template>
<card-box isShared :title="model.name" shadow="hover" class="model-card">
<template #icon>
<span style="height: 32px; width: 32px" :innerHTML="icon"></span>
</template>
<template #title>
<div class="flex" style="height: 22px">
{{ model.name }}
<span v-if="currentModel.status === 'ERROR'">
<el-tooltip effect="dark" :content="errMessage" placement="top">
<el-icon class="danger ml-4" size="18"><Warning /></el-icon>
</el-tooltip>
</span>
<span v-if="currentModel.status === 'PAUSE_DOWNLOAD'">
<el-tooltip
effect="dark"
:content="`${$t('views.model.modelForm.base_model.label')}: ${props.model.model_name} ${$t('views.model.tip.downloadError')}`"
placement="top"
>
<el-icon class="danger ml-4" size="18"><Warning /></el-icon>
</el-tooltip>
</span>
</div>
</template>
<template #subTitle>
<el-text class="color-secondary lighter" size="small">
{{ $t('common.creator') }}: {{ model.username }}
</el-text>
</template>
<ul>
<li class="flex mb-4">
<el-text type="info" class="color-secondary"
>{{ $t('views.model.modelForm.model_type.label') }}
</el-text>
<span class="ellipsis ml-16">
{{ $t(modelType[model.model_type as keyof typeof modelType]) }}</span
>
</li>
<li class="flex">
<el-text type="info" class="color-secondary"
>{{ $t('views.model.modelForm.base_model.label') }}
</el-text>
<span class="ellipsis-1 ml-16" style="height: 20px; width: 70%">
{{ model.model_name }}</span
>
</li>
</ul>
<!-- progress -->
<div class="progress-mask" v-if="currentModel.status === 'DOWNLOAD'">
<!-- <DownloadLoading class="percentage" /> -->
<div class="percentage-label flex-center">
{{ $t('views.model.download.downloading') }} <span class="dotting"></span>
<el-button
link
type="primary"
class="ml-16"
:disabled="!is_permisstion"
@click.stop="cancelDownload"
>{{ $t('views.model.download.cancelDownload') }}
</el-button>
</div>
</div>
<template #mouseEnter>
<el-dropdown trigger="click">
<el-button text @click.stop>
<el-icon>
<MoreFilled />
</el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
icon="EditPen"
:disabled="!is_permisstion"
text
@click.stop="openEditModel"
v-hasPermission="[
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
RoleConst.USER.getWorkspaceRole,
PermissionConst.MODEL_EDIT.getWorkspacePermission,
]"
>
{{ $t('common.modify') }}
</el-dropdown-item>
<el-dropdown-item icon="Lock" @click.stop="openAuthorizedWorkspaceDialog(model)">{{
$t('views.system.shared.authorized_workspace')
}}</el-dropdown-item>
<el-dropdown-item
v-if="
currentModel.model_type === 'TTS' ||
currentModel.model_type === 'LLM' ||
currentModel.model_type === 'IMAGE' ||
currentModel.model_type === 'TTI'
"
:disabled="!is_permisstion"
icon="Setting"
@click.stop="openParamSetting"
v-hasPermission="[
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
RoleConst.USER.getWorkspaceRole,
PermissionConst.MODEL_EDIT.getWorkspacePermission,
]"
>
{{ $t('views.model.modelForm.title.paramSetting') }}
</el-dropdown-item>
<el-dropdown-item
divided
icon="Delete"
:disabled="!is_permisstion"
text
@click.stop="deleteModel"
v-hasPermission="[
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
RoleConst.USER.getWorkspaceRole,
PermissionConst.MODEL_DELETE.getWorkspacePermission,
]"
>
{{ $t('common.delete') }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<EditModel ref="editModelRef" @submit="emit('change')"></EditModel>
<AuthorizedWorkspace ref="AuthorizedWorkspaceDialogRef"></AuthorizedWorkspace>
<ParamSettingDialog ref="paramSettingRef" :model="model" />
</card-box>
</template>
<script setup lang="ts">
import type { Provider, Model } from '@/api/type/model'
import ModelApi from '@/api/system-shared/model'
import { computed, ref, onMounted, onBeforeUnmount } from 'vue'
import EditModel from '@/views/shared/model-shared/component/EditModel.vue'
// import DownloadLoading from '@/components/loading/DownloadLoading.vue'
import { MsgConfirm } from '@/utils/message'
import { modelType } from '@/enums/model'
import useStore from '@/stores'
import ParamSettingDialog from './ParamSettingDialog.vue'
import { t } from '@/locales'
import { PermissionConst, EditionConst, RoleConst } from '@/utils/permission/data'
import AuthorizedWorkspace from '@/views/system-shared/AuthorizedWorkspaceDialog.vue'
const props = defineProps<{
model: Model
provider_list: Array<Provider>
updateModelById: (model_id: string, model: Model) => void
}>()
const { user } = useStore()
const downModel = ref<Model>()
const AuthorizedWorkspaceDialogRef = ref()
const is_permisstion = computed(() => {
return user.userInfo?.id == props.model.user_id
})
const currentModel = computed(() => {
if (downModel.value) {
return downModel.value
} else {
return props.model
}
})
function openAuthorizedWorkspaceDialog(row: any) {
if (AuthorizedWorkspaceDialogRef.value) {
AuthorizedWorkspaceDialogRef.value.open(row, 'Model')
}
}
const errMessage = computed(() => {
if (currentModel.value.meta && currentModel.value.meta.message) {
if (currentModel.value.meta.message === 'pull model manifest: file does not exist') {
return `${currentModel.value.model_name} ${t('views.model.tip.noModel')}`
}
return currentModel.value.meta.message
}
return ''
})
const emit = defineEmits(['change', 'update:model'])
const editModelRef = ref<InstanceType<typeof EditModel>>()
let interval: any
const deleteModel = () => {
MsgConfirm(
t('views.model.delete.confirmTitle'),
`${t('views.model.delete.confirmMessage')}${props.model.name} ?`,
{
confirmButtonText: t('common.confirm'),
confirmButtonClass: 'danger',
},
)
.then(() => {
ModelApi.deleteModel(props.model.id).then(() => {
emit('change')
})
})
.catch(() => {})
}
const cancelDownload = () => {
ModelApi.pauseDownload(props.model.id).then(() => {
downModel.value = undefined
emit('change')
})
}
const openEditModel = () => {
const provider = props.provider_list.find((p) => p.provider === props.model.provider)
if (provider) {
editModelRef.value?.open(provider, props.model)
}
}
const icon = computed(() => {
return props.provider_list.find((p) => p.provider === props.model.provider)?.icon
})
/**
* 初始化轮询
*/
const initInterval = () => {
interval = setInterval(() => {
if (currentModel.value.status === 'DOWNLOAD') {
ModelApi.getModelMetaById(props.model.id).then((ok) => {
downModel.value = ok.data
})
} else {
if (downModel.value) {
props.updateModelById(props.model.id, downModel.value)
downModel.value = undefined
}
}
}, 6000)
}
/**
* 关闭轮询
*/
const closeInterval = () => {
if (interval) {
clearInterval(interval)
}
}
const paramSettingRef = ref<InstanceType<typeof ParamSettingDialog>>()
const openParamSetting = () => {
paramSettingRef.value?.open()
}
onMounted(() => {
initInterval()
})
onBeforeUnmount(() => {
//
closeInterval()
})
</script>
<style lang="scss" scoped>
.model-card {
min-height: 135px;
min-width: auto;
.operation-button {
position: absolute;
right: 12px;
bottom: 12px;
height: auto;
}
.progress-mask {
position: absolute;
top: 0;
left: 0;
background-color: rgba(255, 255, 255, 0.9);
width: 100%;
height: 100%;
z-index: 99;
text-align: center;
.percentage {
margin-top: 55px;
margin-bottom: 16px;
}
// .percentage-value {
// display: flex;
// font-size: 13px;
// align-items: center;
// color: var(--app-text-color-secondary);
// }
.percentage-label {
margin-top: 50px;
margin-left: 10px;
font-size: 13px;
color: var(--app-text-color-secondary);
}
}
}
</style>

View File

@ -1,227 +0,0 @@
<template>
<card-box isShared :title="model.name" shadow="hover" class="model-card">
<template #icon>
<span style="height: 32px; width: 32px" :innerHTML="icon"></span>
</template>
<template #title>
<div class="flex" style="height: 22px">
{{ model.name }}
<span v-if="currentModel.status === 'ERROR'">
<el-tooltip effect="dark" :content="errMessage" placement="top">
<el-icon class="danger ml-4" size="18"><Warning /></el-icon>
</el-tooltip>
</span>
<span v-if="currentModel.status === 'PAUSE_DOWNLOAD'">
<el-tooltip
effect="dark"
:content="`${$t('views.model.modelForm.base_model.label')}: ${props.model.model_name} ${$t('views.model.tip.downloadError')}`"
placement="top"
>
<el-icon class="danger ml-4" size="18"><Warning /></el-icon>
</el-tooltip>
</span>
</div>
</template>
<template #subTitle>
<el-text class="color-secondary lighter" size="small">
{{ $t('common.creator') }}: {{ model.username }}
</el-text>
</template>
<ul>
<li class="flex mb-4">
<el-text type="info" class="color-secondary"
>{{ $t('views.model.modelForm.model_type.label') }}
</el-text>
<span class="ellipsis ml-16">
{{ $t(modelType[model.model_type as keyof typeof modelType]) }}</span
>
</li>
<li class="flex">
<el-text type="info" class="color-secondary"
>{{ $t('views.model.modelForm.base_model.label') }}
</el-text>
<span class="ellipsis-1 ml-16" style="height: 20px; width: 70%">
{{ model.model_name }}</span
>
</li>
</ul>
<!-- progress -->
<div class="progress-mask" v-if="currentModel.status === 'DOWNLOAD'">
<!-- <DownloadLoading class="percentage" /> -->
<div class="percentage-label flex-center">
{{ $t('views.model.download.downloading') }} <span class="dotting"></span>
<el-button
link
type="primary"
class="ml-16"
:disabled="!is_permisstion"
@click.stop="cancelDownload"
>{{ $t('views.model.download.cancelDownload') }}
</el-button>
</div>
</div>
<EditModel ref="editModelRef" @submit="emit('change')"></EditModel>
<ParamSettingDialog ref="paramSettingRef" :model="model" />
</card-box>
</template>
<script setup lang="ts">
import type { Provider, Model } from '@/api/type/model'
import ModelApi from '@/api/system-shared/model'
import { computed, ref, onMounted, onBeforeUnmount } from 'vue'
import EditModel from '@/views/shared/model-shared/component/EditModel.vue'
// import DownloadLoading from '@/components/loading/DownloadLoading.vue'
import { MsgConfirm } from '@/utils/message'
import { modelType } from '@/enums/model'
import useStore from '@/stores'
import AuthorizedWorkspace from '@/views/system-shared/AuthorizedWorkspaceDialog.vue'
import ParamSettingDialog from './ParamSettingDialog.vue'
import { t } from '@/locales'
const props = defineProps<{
model: Model
provider_list: Array<Provider>
updateModelById: (model_id: string, model: Model) => void
}>()
const { user } = useStore()
const downModel = ref<Model>()
const is_permisstion = computed(() => {
return user.userInfo?.id == props.model.user_id
})
const currentModel = computed(() => {
if (downModel.value) {
return downModel.value
} else {
return props.model
}
})
const errMessage = computed(() => {
if (currentModel.value.meta && currentModel.value.meta.message) {
if (currentModel.value.meta.message === 'pull model manifest: file does not exist') {
return `${currentModel.value.model_name} ${t('views.model.tip.noModel')}`
}
return currentModel.value.meta.message
}
return ''
})
const emit = defineEmits(['change', 'update:model'])
const editModelRef = ref<InstanceType<typeof EditModel>>()
let interval: any
const deleteModel = () => {
MsgConfirm(
t('views.model.delete.confirmTitle'),
`${t('views.model.delete.confirmMessage')}${props.model.name} ?`,
{
confirmButtonText: t('common.confirm'),
confirmButtonClass: 'danger',
},
)
.then(() => {
ModelApi.deleteModel(props.model.id).then(() => {
emit('change')
})
})
.catch(() => {})
}
const cancelDownload = () => {
ModelApi.pauseDownload(props.model.id).then(() => {
downModel.value = undefined
emit('change')
})
}
const openEditModel = () => {
const provider = props.provider_list.find((p) => p.provider === props.model.provider)
if (provider) {
editModelRef.value?.open(provider, props.model)
}
}
const icon = computed(() => {
return props.provider_list.find((p) => p.provider === props.model.provider)?.icon
})
/**
* 初始化轮询
*/
const initInterval = () => {
interval = setInterval(() => {
if (currentModel.value.status === 'DOWNLOAD') {
ModelApi.getModelMetaById(props.model.id).then((ok) => {
downModel.value = ok.data
})
} else {
if (downModel.value) {
props.updateModelById(props.model.id, downModel.value)
downModel.value = undefined
}
}
}, 6000)
}
/**
* 关闭轮询
*/
const closeInterval = () => {
if (interval) {
clearInterval(interval)
}
}
const paramSettingRef = ref<InstanceType<typeof ParamSettingDialog>>()
const openParamSetting = () => {
paramSettingRef.value?.open()
}
onMounted(() => {
initInterval()
})
onBeforeUnmount(() => {
//
closeInterval()
})
</script>
<style lang="scss" scoped>
.model-card {
min-height: 135px;
min-width: auto;
.operation-button {
position: absolute;
right: 12px;
bottom: 12px;
height: auto;
}
.progress-mask {
position: absolute;
top: 0;
left: 0;
background-color: rgba(255, 255, 255, 0.9);
width: 100%;
height: 100%;
z-index: 99;
text-align: center;
.percentage {
margin-top: 55px;
margin-bottom: 16px;
}
// .percentage-value {
// display: flex;
// font-size: 13px;
// align-items: center;
// color: var(--app-text-color-secondary);
// }
.percentage-label {
margin-top: 50px;
margin-left: 10px;
font-size: 13px;
color: var(--app-text-color-secondary);
}
}
}
</style>

View File

@ -1,166 +0,0 @@
<template>
<el-dialog
:title="$t('views.model.modelForm.title.paramSetting')"
v-model="dialogVisible"
width="800px"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
:before-close="close"
>
<el-button type="primary" @click="openAddDrawer()" class="mb-12">
{{ $t('views.model.modelForm.title.addParam') }}
</el-button>
<el-table :data="modelParamsForm" class="mb-16">
<el-table-column
prop="label"
:label="$t('dynamicsForm.paramForm.name.label')"
show-overflow-tooltip
>
<template #default="{ row }">
<span v-if="row.label && row.label.input_type === 'TooltipLabel'">{{
row.label.label
}}</span>
<span v-else>{{ row.label }}</span>
</template>
</el-table-column>
<el-table-column
prop="field"
:label="$t('dynamicsForm.paramForm.field.label')"
show-overflow-tooltip
/>
<el-table-column :label="$t('dynamicsForm.paramForm.input_type.label')" width="110px">
<template #default="{ row }">
<el-tag type="info" class="info-tag">{{
input_type_list.find((item) => item.value === row.input_type)?.label
}}</el-tag>
</template>
</el-table-column>
<el-table-column
prop="default_value"
:label="$t('dynamicsForm.default.label')"
show-overflow-tooltip
/>
<el-table-column :label="$t('common.required')">
<template #default="{ row }">
<div @click.stop>
<el-switch disabled size="small" v-model="row.required" />
</div>
</template>
</el-table-column>
<el-table-column :label="$t('common.operation')" align="left" width="90">
<template #default="{ row, $index }">
<span class="mr-4">
<el-tooltip effect="dark" :content="$t('common.modify')" placement="top">
<el-button type="primary" text @click.stop="openAddDrawer(row, $index)">
<el-icon><EditPen /></el-icon>
</el-button>
</el-tooltip>
</span>
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
<el-button type="primary" text @click="deleteParam($index)">
<el-icon>
<Delete />
</el-icon>
</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<template #footer>
<span class="dialog-footer">
<el-button @click="close">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submit" :loading="loading">
{{ $t('common.save') }}
</el-button>
</span>
</template>
</el-dialog>
<AddParamDrawer ref="AddParamRef" @refresh="refresh" />
</template>
<script setup lang="ts">
import type { Model } from '@/api/type/model'
import { ref } from 'vue'
import AddParamDrawer from './AddParamDrawer.vue'
import { MsgError, MsgSuccess } from '@/utils/message'
import ModelApi from '@/api/system-shared/model'
import { input_type_list } from '@/components/dynamics-form/constructor/data'
import { t } from '@/locales'
const props = defineProps<{
model: Model
}>()
const loading = ref<boolean>(false)
const dialogVisible = ref<boolean>(false)
const modelParamsForm = ref<any[]>([])
const AddParamRef = ref()
const open = () => {
dialogVisible.value = true
loading.value = true
ModelApi.getModelParamsForm(props.model.id, loading)
.then((ok) => {
loading.value = false
modelParamsForm.value = ok.data
})
.catch(() => {
loading.value = false
})
}
const close = () => {
dialogVisible.value = false
}
function openAddDrawer(data?: any, index?: any) {
AddParamRef.value?.open(data, index)
}
function deleteParam(index: any) {
modelParamsForm.value.splice(index, 1)
}
function refresh(data: any, index: any) {
for (let i = 0; i < modelParamsForm.value.length; i++) {
const field = modelParamsForm.value[i].field
let label = modelParamsForm.value[i].label
if (label && label.input_type === 'TooltipLabel') {
label = label.label
}
let label2 = data.label
if (label2 && label2.input_type === 'TooltipLabel') {
label2 = label2.label
}
if (field === data.field && index !== i) {
MsgError(t('views.model.tip.errorMessage') + data.field)
return
}
if (label === label2 && index !== i) {
MsgError(t('views.model.tip.errorMessage') + label)
return
}
}
if (index !== null) {
modelParamsForm.value.splice(index, 1, data)
} else {
modelParamsForm.value.push(data)
}
}
function submit() {
ModelApi.updateModelParamsForm(props.model.id, modelParamsForm.value, loading).then(
(ok) => {
MsgSuccess(t('views.model.tip.saveSuccessMessage'))
close()
// emit('submit')
},
)
}
defineExpose({ open, close })
</script>
<style scoped lang="scss"></style>

View File

@ -1,178 +0,0 @@
<template>
<div class="provider-list">
<el-scrollbar>
<div class="p-8">
<div
class="all-mode flex cursor"
@click="clickListHandle(allObj as Provider)"
:class="!active?.provider ? 'all-mode-active color-primary-1' : ''"
>
<AppIcon
class="mr-8 color-primary"
style="height: 20px; width: 20px"
:iconName="'app-all-menu-active'"
></AppIcon>
<span>{{ $t('views.model.modelType.allModel') }}</span>
</div>
<el-collapse class="model-collapse" expand-icon-position="left">
<el-collapse-item
:title="$t('views.model.modelType.publicModel')"
name="1"
icon="CaretRight"
>
<template #title>
<div class="flex align-center">
<AppIcon iconName="app-folder" style="font-size: 20px"></AppIcon>
<span class="ml-8">
{{ $t('views.model.modelType.publicModel') }}
</span>
</div>
</template>
<common-list
:data="online_provider_list"
v-loading="loading"
@click="clickListHandle"
value-key="provider"
default-active=""
ref="commonList1"
>
<template #default="{ row }">
<div class="flex align-center">
<span
:innerHTML="row.icon"
alt=""
style="height: 20px; width: 20px"
class="mr-8"
/>
<span class="ellipsis-1" :title="row.name">{{ row.name }}</span>
</div>
</template>
</common-list>
</el-collapse-item>
<el-collapse-item
:title="$t('views.model.modelType.privateModel')"
name="2"
icon="CaretRight"
>
<template #title>
<div class="flex align-center">
<AppIcon iconName="app-folder" style="font-size: 20px"></AppIcon>
<span class="ml-8">
{{ $t('views.model.modelType.privateModel') }}
</span>
</div>
</template>
<common-list
:data="local_provider_list"
v-loading="loading"
@click="clickListHandle"
value-key="provider"
default-active=""
ref="commonList2"
>
<template #default="{ row }">
<div class="flex align-center">
<span
:innerHTML="row.icon"
alt=""
style="height: 20px; width: 20px"
class="mr-8"
/>
<span class="ellipsis-1" :title="row.name">{{ row.name }}</span>
</div>
</template>
</common-list>
</el-collapse-item>
</el-collapse>
</div>
</el-scrollbar>
</div>
</template>
<script lang="ts" setup>
import { watch, ref } from 'vue'
import type { Provider, Model } from '@/api/type/model'
import { modelTypeList, allObj } from '@/views/shared/model-shared/component/data'
const props = defineProps<{
data: Array<Provider>
loading: boolean
active?: Provider
}>()
const emit = defineEmits(['click'])
const online_provider_list = ref<Array<Provider>>([])
const local_provider_list = ref<Array<Provider>>([])
watch(
() => props.data,
(list) => {
const local_provider = [
'model_ollama_provider',
'model_local_provider',
'model_xinference_provider',
'model_vllm_provider',
]
list
.filter((v) => v.provider)
?.forEach((item) => {
if (local_provider.indexOf(item.provider) > -1) {
local_provider_list.value.push(item)
} else {
online_provider_list.value.push(item)
}
})
online_provider_list.value.sort((a, b) => a.provider.localeCompare(b.provider))
local_provider_list.value.sort((a, b) => a.provider.localeCompare(b.provider))
},
{ immediate: true },
)
const clickListHandle = (item: Provider) => {
emit('click', item)
}
</script>
<style lang="scss" scoped>
.provider-list {
height: calc(var(--app-main-height));
.all-mode {
padding: 10px 8px;
font-weight: 400;
}
.all-mode-active {
border-radius: 4px;
color: var(--el-color-primary);
font-weight: 500 !important;
}
.model-collapse {
border-top: none !important;
border-bottom: none !important;
:deep(.el-collapse-item__header) {
border-bottom: none !important;
padding-left: 8px;
font-size: 14px;
font-weight: 400;
height: 40px;
background: none;
&:hover {
background: var(--app-text-color-light-1);
border-radius: 4px;
}
}
:deep(.el-collapse-item) {
margin-top: 2px;
}
:deep(.common-list) {
li {
padding-left: 50px !important;
}
}
:deep(.el-collapse-item__wrap) {
border-bottom: none !important;
background: none !important;
}
:deep(.el-collapse-item__content) {
padding-bottom: 0 !important;
}
}
}
</style>

View File

@ -1,88 +0,0 @@
<template>
<el-dialog
v-model="dialogVisible"
width="600px"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
:before-close="close"
append-to-body
>
<template #header>
<div class="flex-between">
<h4>{{ $t('views.model.providerPlaceholder') }}</h4>
<el-dropdown>
<span class="cursor">
{{ currentModelType || $t('views..model.modelType.allModel') }}
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="item in modelTypeOptions"
:key="item.value"
@click="checkModelType(item.value)"
>
<span>{{ item.text }}</span>
<el-icon v-if="currentModelType === item.text"><Check /></el-icon>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<el-row :gutter="12" v-loading="loading">
<el-col :span="12" class="mb-16" v-for="(data, index) in list_provider" :key="index">
<el-card shadow="hover" @click="go_create(data)">
<div class="flex align-center cursor">
<span :innerHTML="data.icon" alt="" style="height: 24px; width: 24px" class="mr-8" />
<span>{{ data.name }}</span>
</div>
</el-card>
</el-col>
</el-row>
</el-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import ProviderApi from '@/api/model/provider'
import type { Provider } from '@/api/type/model'
import { modelTypeList } from './data'
import { t } from '@/locales'
const loading = ref<boolean>(false)
const dialogVisible = ref<boolean>(false)
const list_provider = ref<Array<Provider>>([])
const currentModelType = ref('')
const selectModelType = ref('')
const modelTypeOptions = [{ text: t('views.model.modelType.allModel'), value: '' }, ...modelTypeList]
const open = (model_type?: string) => {
dialogVisible.value = true
const option = modelTypeOptions.find((item) => item.text === currentModelType.value)
checkModelType(model_type ? model_type : option ? option.value : '')
}
const close = () => {
dialogVisible.value = false
}
const checkModelType = (model_type: string) => {
selectModelType.value = model_type
currentModelType.value = modelTypeOptions.filter((item) => item.value === model_type)[0].text
ProviderApi.getProviderByModelType(model_type, loading).then((ok) => {
list_provider.value = ok.data
list_provider.value.sort((a, b) => a.provider.localeCompare(b.provider))
})
}
const emit = defineEmits(['change'])
const go_create = (provider: Provider) => {
close()
emit('change', provider, selectModelType.value)
}
defineExpose({ open, close })
</script>
<style lang="scss" scoped></style>

View File

@ -1,18 +0,0 @@
import { modelType } from '@/enums/model'
import { t } from '@/locales'
export const modelTypeList = [
{ text: t(modelType['LLM']), value: 'LLM' },
{ text: t(modelType['EMBEDDING']), value: 'EMBEDDING' },
{ text: t(modelType['RERANKER']), value: 'RERANKER' },
{ text: t(modelType['STT']), value: 'STT' },
{ text: t(modelType['TTS']), value: 'TTS' },
{ text: t(modelType['IMAGE']), value: 'IMAGE' },
{ text: t(modelType['TTI']), value: 'TTI' }
]
export const allObj = {
icon: '',
provider: '',
name: t('views.model.modelType.allModel'),
}

View File

@ -1,249 +0,0 @@
<template>
<div class="model-shared">
<div class="shared-header">
<span class="title">{{ t('views.system.shared.shared_resources') }}</span>
<el-icon size="12">
<rightOutlined></rightOutlined>
</el-icon>
<span class="sub-title">{{ t('views.model.title') }}</span>
</div>
<LayoutContainer>
<template #left>
<h4 class="p-16 mb-8 pb-0">{{ $t('views.model.provider') }}</h4>
<ProviderComponent
:data="provider_list"
@click="clickListHandle"
:loading="loading"
:active="active_provider"
/>
</template>
<ContentContainer
:header="t('views.model.modelType.allModel')"
v-loading="list_model_loading"
>
<template #search>
<div class="flex">
<div class="flex-between complex-search">
<el-select
class="complex-search__left"
v-model="search_type"
style="width: 120px"
@change="search_type_change"
>
<el-option :label="$t('common.creator')" value="create_user" />
<el-option
:label="$t('views.model.modelForm.model_type.label')"
value="model_type"
/>
<el-option :label="$t('views.model.modelForm.modeName.label')" value="name" />
</el-select>
<el-input
v-if="search_type === 'name'"
v-model="model_search_form.name"
@change="list_model"
:placeholder="$t('common.searchBar.placeholder')"
style="width: 220px"
clearable
/>
<el-select
v-else-if="search_type === 'create_user'"
v-model="model_search_form.create_user"
@change="list_model"
clearable
style="width: 220px"
>
<el-option
v-for="u in user_options"
:key="u.id"
:value="u.id"
:label="u.username"
/>
</el-select>
<el-select
v-else-if="search_type === 'model_type'"
v-model="model_search_form.model_type"
clearable
@change="list_model"
style="width: 220px"
>
<template v-for="item in modelTypeList" :key="item.value">
<el-option :label="item.text" :value="item.value" />
</template>
</el-select>
</div>
<el-button class="ml-16" type="primary" @click="openCreateModel(active_provider)">
{{ $t('views.model.addModel') }}</el-button
>
</div>
</template>
<div class="model-list-height">
<el-scrollbar>
<el-row v-if="model_split_list.length > 0" :gutter="15" class="w-full">
<template v-for="(row, index) in model_split_list" :key="index">
<el-col
:xs="24"
:sm="12"
:md="12"
:lg="8"
:xl="6"
class="mb-16"
v-for="(model, i) in row"
:key="i"
>
<ModelCard
@change="list_model"
:updateModelById="updateModelById"
:model="model"
:provider_list="provider_list"
>
</ModelCard>
</el-col>
</template>
</el-row>
<el-empty :description="$t('common.noData')" v-else />
</el-scrollbar>
</div>
</ContentContainer>
<CreateModelDialog
ref="createModelRef"
@submit="list_model"
@change="openCreateModel($event)"
></CreateModelDialog>
<SelectProviderDialog
ref="selectProviderRef"
@change="(provider, modelType) => openCreateModel(provider, modelType)"
></SelectProviderDialog>
</LayoutContainer>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, computed } from 'vue'
import ProviderApi from '@/api/model/provider'
import type { Provider, Model } from '@/api/type/model'
import ModelCard from '@/views/shared/model-shared/component/ModelCard.vue'
import ProviderComponent from '@/views/shared/model-shared/component/Provider.vue'
import { splitArray } from '@/utils/common'
import { modelTypeList, allObj } from '@/views/shared/model-shared/component/data'
import CreateModelDialog from '@/views/shared/model-shared/component/CreateModelDialog.vue'
import iconMap from '@/components/app-icon/icons/common'
import SelectProviderDialog from '@/views/shared/model-shared/component/SelectProviderDialog.vue'
import useStore from '@/stores/modules-shared-system'
import { t } from '@/locales'
const { model } = useStore()
const rightOutlined = iconMap['right-outlined'].iconReader()
const commonList1 = ref()
const commonList2 = ref()
const loading = ref<boolean>(false)
const active_provider = ref<Provider>()
const search_type = ref('name')
const model_search_form = ref<{
name: string
create_user: string
model_type: string
}>({
name: '',
create_user: '',
model_type: '',
})
const user_options = ref<any[]>([])
const list_model_loading = ref<boolean>(false)
const provider_list = ref<Array<Provider>>([])
const model_list = ref<Array<Model>>([])
const updateModelById = (model_id: string, model: Model) => {
model_list.value
.filter((m) => m.id == model_id)
.forEach((m) => {
m.status = model.status
})
}
const model_split_list = computed(() => {
return splitArray(model_list.value, 2)
})
const createModelRef = ref<InstanceType<typeof CreateModelDialog>>()
const selectProviderRef = ref<InstanceType<typeof SelectProviderDialog>>()
const clickListHandle = (item: Provider) => {
active_provider.value = item
list_model()
if (active_provider.value.provider === '') {
commonList1.value.clearCurrent()
commonList2.value.clearCurrent()
}
}
const openCreateModel = (provider?: Provider, model_type?: string) => {
if (provider && provider.provider) {
createModelRef.value?.open(provider, model_type)
} else {
selectProviderRef.value?.open()
}
}
const list_model = () => {
const params = active_provider.value?.provider ? { provider: active_provider.value.provider } : {}
model
.asyncGetModel({ ...model_search_form.value, ...params }, list_model_loading)
.then((ok: any) => {
model_list.value = ok.data
const v = model_list.value.map((m) => ({ id: m.user_id, username: m.username }))
if (user_options.value.length === 0) {
user_options.value = Array.from(new Map(v.map((item) => [item.id, item])).values())
}
})
}
const search_type_change = () => {
model_search_form.value = { name: '', create_user: '', model_type: '' }
}
onMounted(() => {
ProviderApi.getProvider(loading).then((ok) => {
active_provider.value = allObj
provider_list.value = [allObj, ...ok.data]
list_model()
})
})
</script>
<style lang="scss" scoped>
.model-shared {
padding: 21px 14px 16px 24px;
height: 100%;
.shared-header {
color: #646a73;
font-weight: 400;
font-size: 14px;
line-height: 22px;
display: flex;
align-items: center;
margin-bottom: 21px;
:deep(.el-icon i) {
height: 12px;
}
.sub-title {
color: #1f2329;
}
}
.h-full {
border-radius: 8px;
box-shadow: 0px 2px 4px 0px #1f23291f;
background: #fff;
}
}
</style>

View File

@ -1,17 +1,19 @@
<template>
<ContentContainer>
<template #header>
<el-breadcrumb separator-icon="ArrowRight">
<el-breadcrumb-item>{{ t('views.system.shared.shared_resources') }}</el-breadcrumb-item>
<el-breadcrumb-item>
<h5 class="ml-4 color-text-primary">{{ t('views.model.title') }}</h5>
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<el-card style="--el-card-padding: 0">
<modelListContainer />
</el-card>
</ContentContainer>
<div class="shared-model-manage">
<ContentContainer>
<template #header>
<el-breadcrumb separator-icon="ArrowRight">
<el-breadcrumb-item>{{ t('views.system.shared.shared_resources') }}</el-breadcrumb-item>
<el-breadcrumb-item>
<h5 class="ml-4 color-text-primary">{{ t('views.model.title') }}</h5>
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<el-card style="--el-card-padding: 0">
<modelListContainer />
</el-card>
</ContentContainer>
</div>
</template>
<script lang="ts" setup>
@ -22,4 +24,15 @@ import modelListContainer from '@/views/model/index.vue'
onMounted(() => {})
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.shared-model-manage {
padding: 8px 12px 8px 4px;
:deep(.model-list-height) {
height: calc(var(--app-main-height) - 70px);
padding-right: 0 !important;
}
:deep(.provider-list) {
height: calc(var(--app-main-height) - 70px);
}
}
</style>