<template>
|
<div class="container">
|
<Breadcrumb :items="['大模型', '模型管理']" />
|
|
<a-row :gutter="20" align="stretch">
|
<a-col :span="24">
|
<a-card
|
class="general-card"
|
style="min-height: 130px"
|
:title="$t('大模型管理')"
|
>
|
<a-row justify="space-between">
|
<a-col :span="24" class="table_add_clore" v-if="loading">
|
<a-tabs
|
:default-active-key="tabKey"
|
type="line"
|
:editable="true"
|
@tab-click="changeTabs"
|
@add="handleAdd"
|
@delete="handleDelete"
|
show-add-button
|
auto-switch
|
>
|
<a-tab-pane
|
v-for="(item, index) in tabData"
|
:key="index"
|
:title="index"
|
:closable="Object.keys(tabData).length >= 4"
|
>
|
<div
|
style="display: flex; flex-wrap: wrap"
|
class="card_content"
|
>
|
<div class="card-wrap">
|
<div class="card_wrap_box">
|
<div class="card_wrap_box_img">
|
<img
|
:style="{
|
width: '100%',
|
}"
|
alt="暂无图片"
|
:src="item.logo"
|
/>
|
</div>
|
<a-card :bordered="false" hoverable>
|
<div class="arco-card-body-content">
|
<div
|
class="arco-card-body-content-title"
|
style="word-wrap: break-word"
|
>
|
{{ item.tags }}
|
</div>
|
<!-- <div class="arco-card-body-content-dec">{{
|
list.type
|
}}</div> -->
|
</div>
|
</a-card>
|
<div class="arco-btn-group">
|
<a-space class="btn-group">
|
<!-- <editModel></editModel> -->
|
<a-button
|
type="primary"
|
@click="handleEditModel(item, 1)"
|
>
|
编辑
|
</a-button>
|
</a-space>
|
</div>
|
</div>
|
</div>
|
<div
|
class="card-wrap"
|
v-for="(list, index) of item.llm"
|
:key="index"
|
>
|
<div class="card_wrap_box">
|
<div class="card_wrap_box_img">
|
<img
|
:style="{
|
width: '100%',
|
}"
|
alt="暂无图片"
|
:src="list.logo"
|
/>
|
<!-- src="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a20012a2d4d5b9db43dfc6a01fe508c0.png~tplv-uwbnlip3yd-webp.webp" -->
|
</div>
|
<a-card :bordered="false" hoverable>
|
<div class="arco-card-body-content">
|
<div class="arco-card-body-content-title">
|
{{ list.name }}
|
</div>
|
<div class="arco-card-body-content-dec">{{
|
list.type
|
}}</div>
|
</div>
|
</a-card>
|
<div class="arco-btn-group">
|
<a-space class="btn-group">
|
<a-button @click="handleDeleteModel(list)">
|
删除
|
</a-button>
|
<a-button
|
type="primary"
|
@click="handleEditModel(list)"
|
>
|
编辑
|
</a-button>
|
|
<!-- <editModel></editModel> -->
|
</a-space>
|
</div>
|
</div>
|
</div>
|
</div>
|
</a-tab-pane>
|
</a-tabs>
|
</a-col>
|
<div> </div>
|
<div class="box_right">
|
<!-- <div class="search_input">
|
<a-input-search
|
:placeholder="$t('cardList.searchInput.placeholder')"
|
style="width: 240px"
|
/>
|
</div> -->
|
<div>
|
<!-- <addModel></addModel> -->
|
<a-button
|
type="primary"
|
:loading="loading2"
|
@click="handleAddModel"
|
>
|
<template #icon>
|
<icon-plus />
|
</template>
|
添加
|
</a-button>
|
</div>
|
</div>
|
</a-row>
|
</a-card>
|
</a-col>
|
</a-row>
|
<!-- 添加模型 -->
|
<addPageModel
|
v-model:show="show"
|
:task_id="task_id"
|
:type="modelType"
|
:title="title"
|
:editList="editList"
|
@refresh-parent="refreshParentMethod"
|
v-if="show"
|
></addPageModel>
|
<!-- 添加tab模式 -->
|
<addTableName
|
v-model:tabShow="tabShow"
|
:nameList="editList"
|
@refresh-parent="refreshParentMethod"
|
v-if="tabShow"
|
></addTableName>
|
</div>
|
</template>
|
|
<script lang="ts" setup>
|
import { ref, reactive, nextTick } from 'vue';
|
import editModel from '@/views/dmx/model/components/editModel.vue';
|
import addPageModel from './components/addPageModel.vue';
|
import addTableName from './components/addTableName.vue';
|
import {
|
modelList,
|
modelmyLlms,
|
deleteLlm,
|
deleteLlmFactory,
|
} from '@/api/model';
|
import { Modal, Message } from '@arco-design/web-vue';
|
|
let count = 5;
|
const activeKey = ref(1);
|
const data = ref([
|
{
|
key: 1,
|
title: 'key',
|
content: 'Content of Tab Panel 1',
|
},
|
{
|
key: 2,
|
title: 'Ollama',
|
content: 'Content of Tab Panel 2',
|
},
|
{
|
key: 3,
|
title: 'Xinference',
|
content: 'Content of Tab Panel 3',
|
},
|
]);
|
const tabData = ref({
|
key: {
|
tags: '添加key',
|
id: 1,
|
},
|
});
|
|
const isDeleteDialogVisible = ref(false); //删除提醒
|
const apiUrl = ref('http://127.0.0.1:5173');
|
// const httpUrl = import.meta.env.VITE_API_BASE_URL;
|
// console.log(apiUrl.value, 777);
|
const modalList = ref({});
|
const tabKey = ref('key');
|
const changeTabs = (val) => {
|
tabKey.value = val;
|
};
|
const show = ref(false);
|
const tabShow = ref(false);
|
const title = ref('添加模式');
|
const task_id = ref(1);
|
const modelType = ref(1);
|
const handleAdd = () => {
|
tabShow.value = true;
|
editList.value.llm_factory = tabKey.value;
|
};
|
const editList = ref({ llm_factory: '' });
|
//增加模型子类
|
const handleAddModel = () => {
|
modelType.value = 2;
|
editList.value = [{ llm_factory: '' }];
|
editList.value.llm_factory = tabKey.value;
|
show.value = true;
|
title.value = '添加模式';
|
};
|
//编辑模型子类
|
const handleEditModel = (val, type) => {
|
console.log(val, 6766);
|
if (type == 1) {
|
tabShow.value = true;
|
editList.value = val;
|
editList.value.llm_factory = tabKey.value;
|
} else {
|
modelType.value = 2;
|
task_id.value = val.id;
|
show.value = true;
|
title.value = '编辑';
|
editList.value = val;
|
editList.value.llm_factory = tabKey.value;
|
}
|
};
|
|
//删除模型
|
const handleDeleteModel = (val) => {
|
Modal.confirm({
|
title: '警告',
|
content: '确认删除吗',
|
okText: '确定',
|
cancelText: '取消',
|
onOk: async () => {
|
const factory = tabKey.value;
|
const res = await deleteLlm({
|
llm_factory: tabKey.value,
|
llm_name: val.name,
|
});
|
|
if ((res as any).code == 0) {
|
queryModel();
|
tabKey.value = factory;
|
} else {
|
}
|
},
|
onCancel: () => {},
|
});
|
};
|
|
//父级模型
|
const handleDelete = async (key: any) => {
|
console.log(tabData.value[key]);
|
if (tabData.value[key].llm.length > 0) {
|
Message.error('请先删除子模型');
|
return;
|
}
|
if (key !== 'key') {
|
const res = await deleteLlmFactory(key);
|
if (res.code == 200) {
|
Reflect.deleteProperty(tabData.value, key);
|
queryModel();
|
}
|
}
|
};
|
|
const visible = ref(false);
|
const formRef = ref(null);
|
|
const form = reactive({
|
size: 'medium',
|
name: '',
|
});
|
const handleOk = () => {
|
count += 1;
|
formRef.value?.validate().then((res) => {
|
if (res) {
|
return;
|
}
|
data.value = data.value.concat({
|
key: count,
|
title: `${form.name}`,
|
content: ``,
|
});
|
visible.value = false;
|
activeKey.value = count;
|
});
|
nextTick(() => {
|
visible.value = true;
|
});
|
return false;
|
};
|
// const handleCancel = () => {
|
// formRef.value.resetFields();
|
// visible.value = false;
|
// };
|
// const handleSubmit = ({ values, errors }) => {
|
// this.$refs.formRef.validate().then((res, a, b) => {
|
// debugger;
|
// console.log('values', values);
|
// });
|
// };
|
|
//获取模型列表
|
const loading = ref(false);
|
const queryModel = async () => {
|
const res = await modelmyLlms();
|
modalList.value = res.data;
|
loading.value = true;
|
tabData.value = Object.assign({}, tabData.value, res.data);
|
};
|
queryModel();
|
|
const refreshParentMethod = () => {
|
queryModel();
|
// 这里执行需要的操作
|
};
|
</script>
|
|
<script lang="ts">
|
export default {
|
name: 'Card',
|
};
|
</script>
|
|
<style scoped lang="less">
|
.container {
|
padding: 0 20px 20px 20px;
|
:deep(.arco-list-content) {
|
overflow-x: hidden;
|
}
|
|
:deep(.arco-card-meta-title) {
|
font-size: 14px;
|
}
|
}
|
:deep(.arco-list-col) {
|
display: flex;
|
flex-direction: row;
|
flex-wrap: wrap;
|
justify-content: space-between;
|
}
|
|
:deep(.arco-list-item) {
|
width: 33%;
|
}
|
|
:deep(.block-title) {
|
margin: 0 0 12px 0;
|
font-size: 14px;
|
}
|
:deep(.list-wrap) {
|
// min-height: 140px;
|
.list-row {
|
align-items: stretch;
|
.list-col {
|
margin-bottom: 16px;
|
}
|
}
|
:deep(.arco-space) {
|
width: 100%;
|
.arco-space-item {
|
&:last-child {
|
flex: 1;
|
}
|
}
|
}
|
}
|
:deep(.arco-tabs-nav-tab) {
|
flex: none;
|
width: 60%;
|
}
|
.table_add_clore {
|
:deep(.arco-tabs-nav-add-btn .arco-icon-hover::before) {
|
top: 50%;
|
left: 50%;
|
width: 20px;
|
height: 20px;
|
transform: translate(-50%, -50%);
|
border-radius: 0;
|
background-color: #165dff;
|
}
|
|
:deep(.arco-tabs-nav-add-btn .arco-icon-hover .arco-icon) {
|
color: #fff;
|
}
|
// :deep(.arco-tabs-nav) {
|
// max-width: 60%;
|
// }
|
|
:deep(.arco-icon-hover::before) {
|
top: 50%;
|
left: 50%;
|
width: 20px;
|
height: 20px;
|
transform: translate(-50%, -50%);
|
// border-radius: 0;
|
// background-color: #eee;
|
}
|
:deep(.arco-tabs-tab-close-btn .arco-icon) {
|
color: #666;
|
}
|
}
|
.box_right {
|
position: absolute;
|
top: 60px;
|
right: 20px;
|
display: flex;
|
.search_input {
|
margin-right: 10px;
|
}
|
}
|
.arco-card-body-content {
|
.arco-card-body-content-title {
|
font-size: 16px;
|
color: #333;
|
margin-bottom: 10px;
|
font-weight: 400;
|
}
|
}
|
.card_content {
|
.card_wrap_box_img {
|
min-height: 200px;
|
height: 200px;
|
img {
|
max-height: 190px;
|
}
|
}
|
.card_wrap_box {
|
// position: relative;
|
.arco-btn-group {
|
position: absolute;
|
right: 10px;
|
top: 87%;
|
}
|
}
|
}
|
|
.card-wrap {
|
width: 320px;
|
height: 350px;
|
margin: 30px;
|
transition: all 0.3s;
|
border: 1px solid var(--color-neutral-3);
|
border-radius: 4px;
|
&:hover {
|
transform: translateY(-4px);
|
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
|
}
|
}
|
.card-wrap {
|
width: 320px;
|
height: 350px;
|
margin: 30px;
|
transition: all 0.3s;
|
border: 1px solid var(--color-neutral-3);
|
border-radius: 4px;
|
position: relative;
|
&:hover {
|
transform: translateY(-4px);
|
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
|
}
|
}
|
.card-wrap {
|
width: 320px;
|
height: 350px;
|
margin: 30px;
|
transition: all 0.3s;
|
border: 1px solid var(--color-neutral-3);
|
border-radius: 4px;
|
position: relative;
|
&:hover {
|
transform: translateY(-4px);
|
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
|
}
|
:deep(.arco-card) {
|
height: 100%;
|
border-radius: 4px;
|
.arco-card-body {
|
height: 100%;
|
.arco-space {
|
width: 100%;
|
height: 100%;
|
.arco-space-item {
|
height: 100%;
|
&:last-child {
|
flex: 1;
|
}
|
.arco-card-meta {
|
height: 100%;
|
display: flex;
|
flex-flow: column;
|
.arco-card-meta-content {
|
flex: 1;
|
.arco-card-meta-description {
|
margin-top: 8px;
|
color: rgb(var(--gray-6));
|
line-height: 20px;
|
font-size: 12px;
|
}
|
}
|
.arco-card-meta-footer {
|
margin-top: 0;
|
}
|
}
|
}
|
}
|
}
|
}
|
:deep(.arco-card-meta-title) {
|
display: flex;
|
align-items: center;
|
|
// To prevent the shaking
|
line-height: 28px;
|
}
|
:deep(.arco-skeleton-line) {
|
&:last-child {
|
display: flex;
|
justify-content: flex-end;
|
margin-top: 20px;
|
}
|
}
|
}
|
</style>
|