Revert "fetch: 页面移植"

This reverts commit cbc3f329
This commit is contained in:
weike001 2025-02-20 15:34:33 +08:00
parent 26d2033e20
commit b0027f3cb2
3 changed files with 306 additions and 172 deletions

View File

@ -1,185 +1,179 @@
<script lang="ts" setup>
import {Table} from '@/components/Table';
import {Delete, Edit, Plus} from '@element-plus/icons-vue';
import editCom from './edit.vue';
import {computed, h, nextTick, reactive, ref} from 'vue';
import {getColumns} from './composables/columns.ts';
import {LLMProviders} from './composables/consts.ts';
// import { del, list as getModels } from '@/api/aigc/model';
import {ElMessage, ElMessageBox} from 'element-plus';
import {FormSchema} from "@/types/form";
// import { ModelTypeEnum } from '@/api/models';
import {getModels, ProviderEnum} from './composables/provider.ts';
const formData = ref({
provider: ProviderEnum.OPENAI
});
const message = ElMessage;
const dialog = ElMessageBox;
const actionRef = ref();
const editRef = ref();
const tableData = ref([
{
name: '1111'
},
{
name: '1111'
},
{
name: '1111'
},
{
name: '1111'
},
{
name: '1111'
},
{
name: '1111'
},
{
name: '1111'
},
{
name: '1111'
}, {
name: '1111'
},
{
name: '1111'
}
])
// const actionColumn = reactive({
// width: 100,
// title: '',
// key: 'action',
// fixed: 'right',
// align: 'center',
// render(record: any) {
// return h(TableAction as any, {
// style: 'text',
// actions: [
// {
// type: 'info',
// icon: Edit,
// onClick: handleEdit.bind(null, record),
// },
// {
// type: 'error',
// icon: Delete,
// onClick: handleDel.bind(null, record),
// },
// ],
// });
// },
// });
const columns = computed(() => {
nextTick();
return getColumns(formData.value.provider);
});
// const loadDataTable = async (params: any) => {
// if (formData.value.provider === '') {
// formData.value.provider = LLMProviders[0].model;
// }
// return await getModels({ ...params, provider: formData.value.provider, type: ModelTypeEnum.CHAT });
// };
async function addModel() {
console.log(formData.value.provider);
editRef.value.show({provider: formData.value.provider});
}
function handleEdit(record: any) {
editRef.value.show(record);
}
function reloadTable() {
actionRef.value.reload();
}
function handleDel(record: any) {
dialog.warning({
title: '警告',
message: `你确定删除 [${record.name}] 模型吗?删除之后不可再用该模型对话`,
confirmButtonText: '确定',
cancelButtonText: '不确定',
type: 'warning',
}).then(async () => {
await del(record.id);
reloadTable();
message.success('模型删除成功');
}).catch(() => {
//
});
}
</script>
<template> <template>
<!-- <content-wrap>-->
<!-- <el-button v-for="(item,index) in LLMProviders" :key="index" @click="formData.provider = item.model">{{ item.name }}</el-button>-->
<!-- </content-wrap>-->
<ContentWrap> <ContentWrap>
<!-- 搜索工作栏 --> <div class="flex children">
<el-form <el-scrollbar class="h-full w-300px pl-10px pr-20px">
class="-mb-15px" <div
:model="queryParams" v-for="(item,index) in LLMProviders" :key="index"
ref="queryFormRef" :class="{active: formData.provider === item.model}" class="menu"
:inline="true" @click="formData.provider = item.model">
label-width="68px" <span>{{ item.name }}</span>
> </div>
<el-form-item label="模型名字" prop="name"> </el-scrollbar>
<el-input <div class="h-full flex-1 px-20px">
v-model="queryParams.name" <el-alert
placeholder="请输入模型名字" class="w-full mb-10px min-alert"
clearable title="对于完全适配OpenAI接口格式的模型都可在OpenAI中配置只需要定义BaseUrl"
@keyup.enter="handleQuery" type="warning"
class="!w-240px" show-icon
/> />
</el-form-item> <el-button :icon="Plus" class="my-10px" type="primary" @click="addModel">新增模型</el-button>
<el-form-item label="模型标识" prop="model"> <Table class="table-wrapper" height="100%" border :columns="columns" :data="tableData.concat(tableData)" :pagination="false"/>
<el-input <editCom ref="editRef" @reload="reloadTable"/>
v-model="queryParams.model" </div>
placeholder="请输入模型标识" </div>
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="模型平台" prop="platform">
<el-input
v-model="queryParams.platform"
placeholder="请输入模型平台"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['ai:chat-model:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
</el-form-item>
</el-form>
</ContentWrap> </ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="所属平台" align="center" prop="platform">
<template #default="scope">
<dict-tag :type="DICT_TYPE.AI_PLATFORM" :value="scope.row.platform" />
</template>
</el-table-column>
<el-table-column label="模型名字" align="center" prop="name" />
<el-table-column label="模型标识" align="center" prop="model" />
<el-table-column label="API 秘钥" align="center" prop="keyId" min-width="140">
<template #default="scope">
<span>{{ apiKeyList.find((item) => item.id === scope.row.keyId)?.name }}</span>
</template>
</el-table-column>
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="温度参数" align="center" prop="temperature" />
<el-table-column label="回复数 Token 数" align="center" prop="maxTokens" min-width="140" />
<el-table-column label="上下文数量" align="center" prop="maxContexts" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['ai:chat-model:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['ai:chat-model:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ChatModelForm ref="formRef" @success="getList" />
</template> </template>
<script setup lang="ts"> <style lang="scss" scoped>
import { ChatModelApi, ChatModelVO } from '@/api/ai/model/chatModel' .children {
import ChatModelForm from './ChatModelForm.vue' height: calc(100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - (var(--app-content-padding) * 3)) !important;
import { DICT_TYPE } from '@/utils/dict' box-sizing: border-box;
import { ApiKeyApi, ApiKeyVO } from '@/api/ai/model/apiKey'
/** API 聊天模型 列表 */ & > div:nth-child(2) {
defineOptions({ name: 'AiChatModel' }) width: calc(100% - 300px);
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<ChatModelVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: undefined,
model: undefined,
platform: undefined
})
const queryFormRef = ref() //
const apiKeyList = ref([] as ApiKeyVO[]) // API
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ChatModelApi.getChatModelPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
} }
} }
/** 搜索按钮操作 */ .table-wrapper {
const handleQuery = () => { height: calc(100% - 100px);
queryParams.pageNo = 1
getList()
} }
/** 重置按钮操作 */ .menu {
const resetQuery = () => { transition: all .15s;
queryFormRef.value.resetFields() cursor: pointer;
handleQuery() padding: 12px 10px;
} border-radius: 5px;
margin-bottom: 20px;
&.active {
color: #ffffff;
background-color: var(--el-color-primary-light-3);
}
/** 添加/修改操作 */ &:hover {
const formRef = ref() &:not(&.active) {
const openForm = (type: string, id?: number) => { background-color: var(--el-color-info-light-7);
formRef.value.open(type, id) }
}
} }
</style>
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ChatModelApi.deleteChatModel(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 初始化 **/
onMounted(async () => {
getList()
//
apiKeyList.value = await ApiKeyApi.getApiKeySimpleList()
})
</script>

View File

@ -0,0 +1,69 @@
<script setup lang="ts">
import {Plus} from "@element-plus/icons-vue";
import usePage from './composables/index'
import Edit from "@/views/ai/model/embedding/edit.vue";
import {LLMProviders} from "@/views/ai/model/embedding/composables/consts";
import {Table} from "@/components/Table";
const { baseColumns: columns, tableData, formData, editRef, open} = usePage()
</script>
<template>
<ContentWrap>
<div class="children flex">
<el-scrollbar class="h-full w-300px pl-10px pr-20px">
<div
v-for="(item,index) in LLMProviders" :key="index"
:class="{active: formData.provider === item.model}" class="menu"
@click="formData.provider = item.model">
<span>{{ item.name }}</span>
</div>
</el-scrollbar>
<div class="h-full flex-1 px-20px">
<el-alert
class="w-full mb-10px min-alert"
title="注意为了实现向量数据库的动态切换这里Embedding供应商统一选择支持1024纬度的模型"
type="info"
show-icon
/>
<el-button class="my-10px" type="primary" :icon="Plus" @click="open">新增向量模型</el-button>
<Table class="table-wrapper" height="100%" border :columns="columns" :data="tableData.concat(tableData)" :pagination="false"/>
</div>
</div>
<Edit ref="editRef" />
</ContentWrap>
</template>
<style scoped lang="scss">
.children {
height: calc(100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - (var(--app-content-padding) * 3)) !important;
box-sizing: border-box;
& > div:nth-child(2) {
width: calc(100% - 300px);
}
}
.table-wrapper {
height: calc(100% - 100px);
}
.menu {
transition: all .15s;
cursor: pointer;
padding: 12px 10px;
border-radius: 5px;
margin-bottom: 20px;
&.active {
color: #ffffff;
background-color: var(--el-color-primary-light-3);
}
&:hover {
&:not(&.active) {
background-color: var(--el-color-info-light-7);
}
}
}
</style>

View File

@ -0,0 +1,71 @@
<script setup lang="ts">
import {Plus} from "@element-plus/icons-vue";
import usePage from './composables/index'
import {LLMProviders} from "@/views/ai/model/image/composables/consts";
import Edit from './edit.vue'
const {columns, tableData, formData, editRef, open} = usePage()
</script>
<template>
<ContentWrap>
<div class="children flex">
<el-scrollbar class="h-full w-300px pl-10px pr-20px">
<div
v-for="(item,index) in LLMProviders" :key="index"
:class="{active: formData.provider === item.model}" class="menu"
@click="formData.provider = item.model">
<span>{{ item.name }}</span>
</div>
</el-scrollbar>
<div class="h-full p-20px">
<el-alert
class="w-full mb-10px min-alert"
show-icon
title="鉴于很多模型的文生图效果很差甚至没有这里只建议使用OpenAI的DALL-E模型"
type="info"
/>
<el-button :icon="Plus" class="my-10px" type="primary" @click="open">新增向量模型
</el-button>
<Table :columns="columns" :data="tableData.concat(tableData)" :pagination="false" border
class="table-wrapper" height="100%"/>
</div>
</div>
<Edit ref="editRef"/>
</ContentWrap>
</template>
<style scoped lang="scss">
.children {
height: calc(100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - (var(--app-content-padding) * 3)) !important;
box-sizing: border-box;
& > div:nth-child(2) {
width: calc(100% - 300px);
}
}
.table-wrapper {
height: calc(100% - 100px);
}
.menu {
transition: all .15s;
cursor: pointer;
padding: 12px 10px;
border-radius: 5px;
margin-bottom: 20px;
&.active {
color: #ffffff;
background-color: var(--el-color-primary-light-3);
}
&:hover {
&:not(&.active) {
background-color: var(--el-color-info-light-7);
}
}
}
</style>