You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

542 lines
16 KiB
Vue

<template>
<a-spin tip="加载中..." :spinning="loading">
<div class="page-out">
<div class="title">
<div class="search-div">
<a-input class="search-input" v-model:value="searchValue" placeholder="搜索实例名称…">
<template #prefix>
<div class="search-input-icon"></div>
</template>
</a-input>
<a-select
placeholder="请选择算法"
class="select-algorithm"
v-model:value="instanceAlgorithm"
:options="algorithmOptions"
/>
<a-button class="search-button" type="primary" @click="query"></a-button>
</div>
<a-button class="add-instance" type="primary" :icon="h(PlusOutlined)" @click="changeAddModal(true)"></a-button>
</div>
<div class="show-list-div">
<div class="show-list">
<div class="item-list" v-for="item in dataList">
<div class="image-div">
<img class="image-item" :src="`${VITE_GLOB_API_URL}/${item.cover}`">
<!--<div class="image-icon">盖板缺失</div> -->
</div>
<div class="show-info-div">
<div class="info-title-div">
<div class="info-icon"></div>
<div class="info-title-inner">
<div class="info-title">{{ item.name }}</div>
<div style="display: flex;justify-content: space-between;">
<div class="info-subtitle">{{ item.description? item.description: '暂无描述' }}</div>
</div>
</div>
</div>
<div class="info-content-div">
<div class="content-div">
<div class="content-title-div">关联算法</div>
<div class="content-info" v-html="getContentStr(item.algoNames)"></div>
</div>
<div class="button-div">
<div style="margin-bottom: 13px;">
<a-button class="delete-button" @click="delData(item)">删除</a-button>
</div>
<div>
<a-button class="show-info-button" type="primary" @click="showInfo(item)">查看</a-button>
</div>
</div>
</div>
</div>
<!-- <div class="item-footer">
<a-button class="item-del" @click="delData(item)">删除</a-button>
<a-button class="item-show" type="primary" @click="showInfo(item)">查看</a-button>
</div> -->
</div>
</div>
<div class="pagination-div">
<a-pagination
size="small"
:total="total"
v-model:current="page"
v-model:page-size="limit"
show-size-changer
show-quick-jumper
:show-total="total => `共 ${total} 条数据`"
@change="changePagination"
/>
</div>
</div>
<a-modal width="853px" v-model:open="addInstanceModal" :footer="false" :closable="false" :destroyOnClose="true" :maskClosable="false" :keyboard="false">
<AddInstanceModal :modalType="modalType" :showInfoData="showInfoData" :algorithmOptions="algorithmOptions" @changeAddModal="changeAddModal" @query="query"/>
</a-modal>
<a-drawer
width="442px"
:closable="false"
v-model:open="showInfoDrawer"
placement="right"
rootClassName="instance-show-info-drawer"
>
<ShowInfoDrawer :showInfoData="showInfoData" @changeDrawerModal="changeDrawerModal" @changeAddModal="changeAddModal"/>
</a-drawer>
</div>
</a-spin>
</template>
<script setup lang="ts">
import { ref, h, onMounted, createVNode } from "vue"
import { ExclamationCircleOutlined, PlusOutlined, } from '@ant-design/icons-vue';
import AddInstanceModal from "./AddInstanceModal.vue";
import ShowInfoDrawer from "./ShowInfoDrawer.vue";
import { getAppEnvConfig } from '@/utils/env';
import { GetAlgoInstanceList, DeleteAlgoInstance } from '@/api/demo/aiinstance'
import { GetAlgorithmsRepositoryList } from '@/api/demo/ailist'
import { DataListType } from './utils'
import { message, Modal } from "ant-design-vue";
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const searchValue = ref('')
const instanceAlgorithm = ref()
const addInstanceModal = ref(false)
const showInfoDrawer = ref(false)
const page = ref('1')
const limit = ref('10')
const total = ref('0')
const dataList = ref<DataListType[]>([])
const loading = ref(false)
const algorithmOptions = ref([])
const showInfoData = ref({})
const modalType = ref('')
onMounted(() => {
GetAlgorithmsRepositoryList({page:1,limit: 999}).then(res => {
algorithmOptions.value = res.items.map(item => {
return {
label: item.name,
value: item.id,
modelLabels: item.modelLabels
}
})
})
query()
})
const query = () => {
loading.value = true
let params = {
page: page.value,
limit: limit.value,
key: searchValue.value,
}
GetAlgoInstanceList(params).then(res => {
console.log('res',res)
total.value = res.total
dataList.value = res.items
}).finally(() => {
loading.value = false
})
}
const changePagination = () => {
query()
}
const changeAddModal = (type: boolean, isInsert:boolean = true) => {
console.log('type',type,'isInsert',isInsert)
if(type){
if(isInsert){
modalType.value = 'insert'
}else{
modalType.value = 'update'
changeDrawerModal(false)
}
}
addInstanceModal.value = type
}
const showInfo = (item) => {
showInfoData.value = item
changeDrawerModal(true)
}
const changeDrawerModal = (type: boolean) => {
showInfoDrawer.value = type
}
const delData = (item) => {
Modal.confirm({
title: `确认删除 ${item.name} 吗?`,
icon: createVNode(ExclamationCircleOutlined),
okText: '确认',
cancelText: '取消',
centered: true,
onOk() {
return DeleteAlgoInstance({id: item.id}).then(res => {
message.success("删除成功")
query()
})
},
});
}
const getContentStr = (list: string[]) => {
return list.map( item => `#${item}`).join('<br/>')
}
</script>
<style lang="scss" scoped>
.page-out{
padding: 16px 30px 33px 17px;
width: 100%;
height: calc(100vh - 80px);
.title{
height: 58px;
background: #fff;
padding-left: 28px;
padding-right: 36px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 17px;
.search-div{
display: flex;
align-items: center;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 16px;
line-height: 28px;
.search-input{
width: 232px;
height: 36px;
background: #FFFFFF;
border-radius: 4px;
border: 1px solid #30384F;
margin-right: 13px;
.search-input-icon{
width: 18px;
height: 18px;
background-image: url('/public/ailist/search_input_icon.png');
}
}
.select-algorithm{
margin-right: 13px;
:deep(.ant-select-selector){
width: 191px;
height: 36px;
background: #FFFFFF;
border-radius: 4px;
border: 1px solid #30384F;
}
:deep(.ant-select-selection-placeholder){
line-height: 34px;
}
}
.search-button{
width: 80px;
height: 36px;
background: #0B60BD;
border-radius: 4px;
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 16px;
color: #FFFFFF;
line-height: 22px;
}
}
.add-instance{
width: 148px;
height: 36px;
background: #0B60BD;
border-radius: 4px;
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 16px;
color: #FFFFFF;
line-height: 22px;
}
}
.show-list-div{
width: 100%;
height: calc(100% - 60px);
background: #fff;
padding: 26px 26px 0px 26px;
.show-list{
min-height: calc(100% - 69px);
display: flex;
flex-wrap: wrap;
gap: 20px;
padding-bottom: 20px;
overflow: auto;
scrollbar-width: none;
::-webkit-scrollbar{
width: 0;
height: 0;
}
.item-list{
width: 300px;
height: 321px;
background: #FFFFFF;
box-shadow: 5px 18px 32px 0px rgba(28,29,34,0.1);
border-radius: 10px;
.image-div{
position: relative;
width: 300px;
height: 200px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
margin-bottom: 10px;
.image-item{
width: 300px;
height: 200px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
.image-icon{
position: absolute;
top: 0px;
left: 0px;
width: 46px;
height: 16px;
background: linear-gradient( 320deg, #6C90F5 0%, #3A57E8 100%);
border-radius: 8px 0px 8px 0px;
display: flex;
align-items: center;
justify-content: center;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 9px;
color: #FFFFFF;
line-height: 12px;
}
}
.show-info-div{
padding-left: 9px;
padding-right: 12px;
.info-title-div{
height: 40px;
display: flex;
align-items: center;
margin-bottom: 4px;
.info-icon{
width: 3px;
height: 34px;
background: #0B60BD;
margin-right: 5px;
}
.info-title-inner{
width: calc(100% - 8px);
.info-title{
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 14px;
color: #1C1D22;
line-height: 20px;
margin-bottom: 5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.info-subtitle{
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 11px;
color: rgba(28,29,34,0.5);
line-height: 15px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.show-more-info{
display: flex;
align-items: center;
user-select: none;
cursor: pointer;
.show-more-span{
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 11px;
color: #1C1D22;
line-height: 15px;
margin-right: 6px;
}
.show-more-icon{
width: 12px;
height: 8px;
background-image: url('/public/instance/instance_show_more_icon.png');
}
}
}
}
.info-content-div{
display: flex;
.content-div{
width: 200px;
margin-top: 4px;
padding-top: 8px;
border-top: 1px dashed rgba(151, 151, 151, 0.37);
margin-right: 27px;
.content-title-div{
display: flex;
align-items: center;
justify-content: center;
width: 47px;
height: 19px;
background: rgba(216, 216, 216,0.34);
border-radius: 2px;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 10px;
color: #1C1D22;
line-height: 14px;
}
.content-info{
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 10px;
color: #1C1D22;
line-height: 14px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
}
.button-div{
.delete-button{
display: flex;
align-items: center;
justify-content: center;
width: 54px;
height: 23px;
border-radius: 2px;
border: 1px solid #F2F2F2;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 11px;
color: #E3150E;
line-height: 15px;
}
.show-info-button{
display: flex;
align-items: center;
justify-content: center;
width: 54px;
height: 23px;
background: #0B60BD;
border-radius: 2px;
border: 1px solid #0B60BD;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 11px;
color: #FFFFFF;
line-height: 15px;
}
}
}
// .info-content-div{
// width: 100%;
// height: 66px;
// background-image: url('/public/instance/instance_list_item_info_content.png');
// padding-top: 8px;
// padding-left: 12px;
// margin-bottom: 13px;
// .content-raw{
// display: flex;
// .content-label{
// font-family: PingFangSC-Regular;
// font-weight: 400;
// font-size: 12px;
// color: #1C1D22;
// line-height: 17px;
// margin-right: 11px;
// }
// .content-value{
// font-family: PingFangSC-Medium;
// font-weight: 500;
// font-size: 12px;
// color: #1C1D22;
// line-height: 17px;
// }
// }
// }
}
// .item-footer{
// width: 100%;
// height: 23px;
// display: flex;
// align-items: center;
// justify-content: end;
// padding-right: 12px;
// .item-del{
// width: 54px;
// height: 23px;
// border-radius: 2px;
// border: 1px solid #F2F2F2;
// margin-right: 7px;
// font-family: PingFangSC-Regular;
// font-weight: 400;
// font-size: 11px;
// color: #E3150E;
// line-height: 15px;
// }
// .item-show{
// width: 54px;
// height: 23px;
// background: #0B60BD;
// border-radius: 2px;
// border: 1px solid #0B60BD;
// font-family: PingFangSC-Regular;
// font-weight: 400;
// font-size: 11px;
// color: #FFFFFF;
// line-height: 15px;
// }
// }
}
}
.pagination-div{
padding-right: 32px;
// width: 100%;
height: 69px;
display: flex;
align-items: center;
justify-content: end;
border-top: 1px solid rgba(28,29,34,0.08);
margin-left: -26px;
margin-right: -26px;
padding-right: 45px;
}
}
}
</style>
<style lang="scss">
.instance-show-more-info-popover{
.ant-popover-inner{
background-color: rgba(5, 5, 5, 0.56);
}
.show-more-content{
width: 232px;
.content-raw{
display: flex;
.content-label{
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 12px;
color: #FFFFFF;
line-height: 17px;
margin-right: 11px;
}
.content-value{
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 12px;
color: #FFFFFF;
line-height: 17px;
}
}
}
}
.instance-show-info-drawer{
.ant-drawer-body{
padding: 0px;
}
}
</style>