|
|
|
@ -1,11 +1,11 @@ |
|
|
|
<script lang="ts" setup> |
|
|
|
import { Card, Dropdown, Menu, Popconfirm } from 'ant-design-vue' |
|
|
|
import type { PropType } from 'vue' |
|
|
|
import { ref, watch } from 'vue' |
|
|
|
import { onBeforeUnmount, onMounted, ref, watch } from 'vue' |
|
|
|
import type { ModelItem } from './data' |
|
|
|
import Icon from '@/components/Icon/index' |
|
|
|
import { modelCardListApi, modelDeleteApi } from '@/api/alert/model/models' |
|
|
|
import type { ModelQueryParams } from '@/api/alert/model/model/models' |
|
|
|
import type { ModelCardQueryParams } from '@/api/alert/model/model/models' |
|
|
|
import { useGo } from '@/hooks/web/usePage' |
|
|
|
import { useMessage } from '@/hooks/web/useMessage' |
|
|
|
|
|
|
|
@ -34,12 +34,19 @@ function changeModel(id, version?) { |
|
|
|
} |
|
|
|
|
|
|
|
const modelCardList = ref<Array<ModelItem>>([]) |
|
|
|
const lastQuery = ref<ModelQueryParams | null>(null) |
|
|
|
const rootRef = ref<HTMLElement | null>(null) |
|
|
|
const loadMoreTriggerRef = ref<HTMLElement | null>(null) |
|
|
|
const lastQuery = ref<ModelCardQueryParams | null>(null) |
|
|
|
const pageNo = ref(1) |
|
|
|
const pageSize = 25 |
|
|
|
const listLoading = ref(false) |
|
|
|
const noMore = ref(false) |
|
|
|
let loadMoreObserver: IntersectionObserver | null = null |
|
|
|
const colors = ['#8dc63f', '#dbb09e'] |
|
|
|
const statusStr = ['未下装', '已下装'] |
|
|
|
const statusIcons = ['ant-design:unlock-outlined', 'ant-design:lock-outlined'] |
|
|
|
|
|
|
|
function buildQuery(value: any): ModelQueryParams { |
|
|
|
function buildQuery(value: any): ModelCardQueryParams { |
|
|
|
return { |
|
|
|
unitId: value?.unit, |
|
|
|
typeId: value?.type, |
|
|
|
@ -48,14 +55,7 @@ function buildQuery(value: any): ModelQueryParams { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async function loadModelList(value: any) { |
|
|
|
const queryParams = buildQuery(value) |
|
|
|
lastQuery.value = queryParams |
|
|
|
const modelList = await modelCardListApi(queryParams) |
|
|
|
if (!modelList) { |
|
|
|
modelCardList.value = [] |
|
|
|
return |
|
|
|
} |
|
|
|
function normalizeCards(modelList: any[] = []): ModelItem[] { |
|
|
|
const cardList: ModelItem[] = [] |
|
|
|
for (const modelCard of modelList) { |
|
|
|
const statusIndex = Number(modelCard.status) || 0 |
|
|
|
@ -78,7 +78,40 @@ async function loadModelList(value: any) { |
|
|
|
} |
|
|
|
cardList.push(card) |
|
|
|
} |
|
|
|
modelCardList.value = cardList |
|
|
|
return cardList |
|
|
|
} |
|
|
|
|
|
|
|
async function fetchModelList(queryParams: ModelCardQueryParams, append: boolean) { |
|
|
|
if (listLoading.value) |
|
|
|
return |
|
|
|
listLoading.value = true |
|
|
|
try { |
|
|
|
const pageResult = await modelCardListApi({ |
|
|
|
...queryParams, |
|
|
|
pageNo: pageNo.value, |
|
|
|
pageSize, |
|
|
|
}) |
|
|
|
if (!pageResult) { |
|
|
|
modelCardList.value = [] |
|
|
|
noMore.value = true |
|
|
|
return |
|
|
|
} |
|
|
|
const records = pageResult.records || [] |
|
|
|
const cardList = normalizeCards(records) |
|
|
|
modelCardList.value = append ? modelCardList.value.concat(cardList) : cardList |
|
|
|
noMore.value = pageResult.pages ? pageResult.current >= pageResult.pages : records.length < pageSize |
|
|
|
} |
|
|
|
finally { |
|
|
|
listLoading.value = false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async function loadModelList(value: any) { |
|
|
|
pageNo.value = 1 |
|
|
|
noMore.value = false |
|
|
|
const queryParams = buildQuery(value) |
|
|
|
lastQuery.value = queryParams |
|
|
|
await fetchModelList(queryParams, false) |
|
|
|
} |
|
|
|
|
|
|
|
watch( |
|
|
|
@ -103,16 +136,64 @@ function goCreateModel() { |
|
|
|
query.push(`unitId=${encodeURIComponent(String(props.unitId))}`) |
|
|
|
go(`/model/create${query.length ? `?${query.join('&')}` : ''}`) |
|
|
|
} |
|
|
|
|
|
|
|
async function loadMore() { |
|
|
|
if (listLoading.value || noMore.value || !lastQuery.value) |
|
|
|
return |
|
|
|
pageNo.value += 1 |
|
|
|
await fetchModelList(lastQuery.value, true) |
|
|
|
} |
|
|
|
|
|
|
|
function getScrollParent(el: HTMLElement | null) { |
|
|
|
let current = el?.parentElement || null |
|
|
|
while (current) { |
|
|
|
const style = window.getComputedStyle(current) |
|
|
|
if (/(auto|scroll)/.test(style.overflowY)) |
|
|
|
return current |
|
|
|
current = current.parentElement |
|
|
|
} |
|
|
|
return null |
|
|
|
} |
|
|
|
|
|
|
|
function initLoadMoreObserver() { |
|
|
|
if (loadMoreObserver) { |
|
|
|
loadMoreObserver.disconnect() |
|
|
|
loadMoreObserver = null |
|
|
|
} |
|
|
|
const target = loadMoreTriggerRef.value |
|
|
|
if (!target) |
|
|
|
return |
|
|
|
const root = getScrollParent(rootRef.value) |
|
|
|
loadMoreObserver = new IntersectionObserver( |
|
|
|
(entries) => { |
|
|
|
if (entries.some(entry => entry.isIntersecting)) |
|
|
|
loadMore() |
|
|
|
}, |
|
|
|
{ root, rootMargin: '160px 0px' }, |
|
|
|
) |
|
|
|
loadMoreObserver.observe(target) |
|
|
|
} |
|
|
|
|
|
|
|
onMounted(() => { |
|
|
|
initLoadMoreObserver() |
|
|
|
}) |
|
|
|
|
|
|
|
onBeforeUnmount(() => { |
|
|
|
if (loadMoreObserver) { |
|
|
|
loadMoreObserver.disconnect() |
|
|
|
loadMoreObserver = null |
|
|
|
} |
|
|
|
}) |
|
|
|
</script> |
|
|
|
|
|
|
|
<template> |
|
|
|
<div class="enter-y"> |
|
|
|
<div ref="rootRef" class="enter-y"> |
|
|
|
<div class="card-grid"> |
|
|
|
<template v-for="item in modelCardList" :key="item.title"> |
|
|
|
<Dropdown :trigger="['contextmenu']"> |
|
|
|
<Card |
|
|
|
size="small" |
|
|
|
:loading="loading" |
|
|
|
:loading="loading || (listLoading && !modelCardList.length)" |
|
|
|
:hoverable="true" |
|
|
|
class="model-card" |
|
|
|
:style="{ borderLeft: `6px solid ${item.statusColor}` }" |
|
|
|
@ -168,6 +249,14 @@ function goCreateModel() { |
|
|
|
<Icon icon="ic:sharp-add" :size="80" color="#a7a9a7" /> |
|
|
|
</Card> |
|
|
|
</div> |
|
|
|
<div ref="loadMoreTriggerRef" class="load-more-trigger" /> |
|
|
|
<div v-if="modelCardList.length" class="load-status"> |
|
|
|
<span v-if="listLoading">加载中...</span> |
|
|
|
<span v-else-if="noMore">没有更多了</span> |
|
|
|
</div> |
|
|
|
<div v-else-if="!listLoading" class="load-status empty"> |
|
|
|
暂无数据 |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
@ -315,4 +404,19 @@ function goCreateModel() { |
|
|
|
background-color: #eef2ff; |
|
|
|
border-color: #4c7af0; |
|
|
|
} |
|
|
|
|
|
|
|
.load-status { |
|
|
|
padding: 12px 0 4px; |
|
|
|
font-size: 12px; |
|
|
|
color: #9ca3af; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.load-status.empty { |
|
|
|
padding-top: 24px; |
|
|
|
} |
|
|
|
|
|
|
|
.load-more-trigger { |
|
|
|
height: 1px; |
|
|
|
} |
|
|
|
</style> |
|
|
|
|