diff --git a/inventory-web/src/views/stock/inbound/service.vue b/inventory-web/src/views/stock/inbound/service.vue
index 05d9112..efed232 100644
--- a/inventory-web/src/views/stock/inbound/service.vue
+++ b/inventory-web/src/views/stock/inbound/service.vue
@@ -110,6 +110,8 @@
style="width: 100%"
@change="onMaterialSelected"
default-first-option
+ v-loadmore="loadMoreMaterials"
+ popper-class="long-dropdown"
>
{{ item.spec }}
+
+ 加载中...
+
@@ -260,6 +265,26 @@ const hasFormFieldPermission = (fieldName: string) => {
return userStore.hasPermission(code)
}
+// 自定义指令:v-loadmore(适配 Teleport 到 Body 的下拉框)
+const vLoadmore = {
+ mounted(el: any, binding: any) {
+ const checkAndBind = () => {
+ const dropDownWrap = document.querySelector('.long-dropdown .el-select-dropdown__wrap')
+ if (dropDownWrap && !dropDownWrap.getAttribute('data-loadmore-bound')) {
+ dropDownWrap.setAttribute('data-loadmore-bound', 'true')
+ dropDownWrap.addEventListener('scroll', function (this: any) {
+ const condition = this.scrollHeight - this.scrollTop <= this.clientHeight + 1
+ if (condition) {
+ binding.value()
+ }
+ })
+ }
+ }
+ setTimeout(checkAndBind, 500)
+ el.addEventListener('click', () => setTimeout(checkAndBind, 300))
+ }
+}
+
// 表格数据
const tableData = ref([])
const loading = ref(false)
@@ -269,6 +294,10 @@ const total = ref(0)
const materialOptions = ref([])
const searchLoading = ref(false)
+const searchPage = ref(1)
+const hasNextPage = ref(true)
+const loadingMore = ref(false)
+const searchKeyword = ref('')
const searchForm = reactive({
keyword: '',
@@ -335,11 +364,15 @@ const handleMaterialDropdownVisible = (visible: boolean) => {
const handleSearchMaterial = async (query: string) => {
searchLoading.value = true
+ searchKeyword.value = query
+ searchPage.value = 1
+ materialOptions.value = []
try {
- const res = await searchMaterialBase(query)
+ const res: any = await searchMaterialBase(query, 1)
if (res.code === 200) {
- const apiResults = (res.data || []).map((i: any) => ({ ...i, isHistory: false }))
+ const apiResults = (res.data?.items || []).map((i: any) => ({ ...i, isHistory: false }))
materialOptions.value = apiResults
+ hasNextPage.value = res.data?.has_next ?? false
} else {
materialOptions.value = []
}
@@ -350,6 +383,26 @@ const handleSearchMaterial = async (query: string) => {
}
}
+const loadMoreMaterials = async () => {
+ if (searchLoading.value || loadingMore.value || !hasNextPage.value) return
+ loadingMore.value = true
+ searchPage.value += 1
+ try {
+ const res: any = await searchMaterialBase(searchKeyword.value, searchPage.value)
+ if (res.data && res.data.items && res.data.items.length > 0) {
+ const newItems = res.data.items.map((i: any) => ({ ...i, isHistory: false }))
+ materialOptions.value.push(...newItems)
+ hasNextPage.value = res.data.has_next
+ } else {
+ hasNextPage.value = false
+ }
+ } catch (e) {
+ searchPage.value -= 1
+ } finally {
+ loadingMore.value = false
+ }
+}
+
const onMaterialSelected = (val: number) => {
const item = materialOptions.value.find(i => i.id === val)
if (item) {