Files
crm_uiapp/src/pages-erp/stock/index.vue

239 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="yd-page-container">
<!-- 顶部导航栏 -->
<wd-navbar
title="库存查询"
left-arrow placeholder safe-area-inset-top fixed
@click-left="handleBack"
/>
<!-- 搜索组件 -->
<view @click="searchVisible = true">
<wd-search :placeholder="searchPlaceholder" hide-cancel disabled />
</view>
<!-- 库存列表 -->
<view class="px-24rpx">
<view
v-for="item in list"
:key="item.id"
class="mb-20rpx overflow-hidden rounded-12rpx bg-white shadow-sm"
>
<view class="p-24rpx">
<!-- 头部产品名称 + 分类 -->
<view class="mb-16rpx flex items-center justify-between">
<view class="text-30rpx text-[#333] font-semibold">
{{ item.productName || '-' }}
</view>
<view class="text-24rpx text-[#999]">
{{ item.categoryName || '' }}
</view>
</view>
<!-- 单位 -->
<view class="mb-8rpx flex items-center justify-between text-26rpx text-[#666]">
<text class="text-[#999]">单位</text>
<text>{{ item.unitName || '-' }}</text>
</view>
<!-- 仓库 -->
<view class="mb-12rpx flex items-center justify-between text-26rpx text-[#666]">
<text class="text-[#999]">仓库</text>
<text>{{ item.warehouseName || '-' }}</text>
</view>
<!-- 库存量 -->
<view class="flex items-center justify-around mt-12rpx pt-16rpx border-t border-[#f0f0f0]">
<view class="text-center">
<view class="text-36rpx text-[#1890ff] font-semibold">{{ formatCount(item.count) }}</view>
<view class="text-22rpx text-[#999] mt-4rpx">库存量</view>
</view>
</view>
</view>
</view>
<!-- 加载更多 -->
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="py-100rpx text-center">
<wd-status-tip image="content" tip="暂无库存数据" />
</view>
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
</view>
<!-- 搜索弹窗 -->
<wd-popup v-model="searchVisible" position="top" @close="searchVisible = false">
<view class="yd-search-form-container" :style="{ paddingTop: `${getNavbarHeight()}px` }">
<view class="yd-search-form-item">
<view class="yd-search-form-label">产品</view>
<wd-picker
v-model="searchForm.productId"
:columns="productColumns"
label=""
placeholder="请选择产品"
@confirm="onProductConfirm"
/>
</view>
<view class="yd-search-form-item">
<view class="yd-search-form-label">仓库</view>
<wd-picker
v-model="searchForm.warehouseId"
:columns="warehouseColumns"
label=""
placeholder="请选择仓库"
@confirm="onWarehouseConfirm"
/>
</view>
<view class="yd-search-form-actions">
<wd-button class="flex-1" plain @click="handleReset">重置</wd-button>
<wd-button class="flex-1" type="primary" @click="handleSearch">搜索</wd-button>
</view>
</view>
</wd-popup>
</view>
</template>
<script lang="ts" setup>
import type { Stock } from '@/api/erp/stock'
import type { LoadMoreState } from '@/http/types'
import { onReachBottom } from '@dcloudio/uni-app'
import { computed, onMounted, reactive, ref } from 'vue'
import { getStockPage } from '@/api/erp/stock'
import { getWarehouseSimpleList } from '@/api/erp/warehouse'
import { getNavbarHeight, navigateBackPlus } from '@/utils'
definePage({
style: {
navigationBarTitleText: '',
navigationStyle: 'custom',
},
})
const total = ref(0)
const list = ref<Stock[]>([])
const loadMoreState = ref<LoadMoreState>('loading')
const queryParams = ref<Record<string, any>>({
pageNo: 1,
pageSize: 10,
})
// 搜索相关
const searchVisible = ref(false)
const searchForm = reactive({
productId: undefined as number | undefined,
warehouseId: undefined as number | undefined,
})
// 产品和仓库列表
const productList = ref<{ id: number, name: string }[]>([])
const warehouseList = ref<{ id: number, name: string }[]>([])
/** 产品下拉列 */
const productColumns = computed(() => [
[{ value: '', label: '全部' }, ...productList.value.map(v => ({ value: v.id, label: v.name }))],
])
/** 仓库下拉列 */
const warehouseColumns = computed(() => [
[{ value: '', label: '全部' }, ...warehouseList.value.map(v => ({ value: v.id, label: v.name }))],
])
/** 产品选择回调 */
function onProductConfirm({ value }: any) {
searchForm.productId = value?.[0] || undefined
}
/** 仓库选择回调 */
function onWarehouseConfirm({ value }: any) {
searchForm.warehouseId = value?.[0] || undefined
}
/** 搜索条件 placeholder */
const searchPlaceholder = computed(() => {
const conditions: string[] = []
if (searchForm.productId) {
const product = productList.value.find(p => p.id === searchForm.productId)
if (product) conditions.push(`产品:${product.name}`)
}
if (searchForm.warehouseId) {
const warehouse = warehouseList.value.find(w => w.id === searchForm.warehouseId)
if (warehouse) conditions.push(`仓库:${warehouse.name}`)
}
return conditions.length > 0 ? conditions.join(' | ') : '搜索库存'
})
/** 格式化数量 */
function formatCount(count?: number) {
if (count === undefined || count === null) return '-'
return count.toFixed(2)
}
/** 返回上一页 */
function handleBack() {
navigateBackPlus()
}
/** 查询库存列表 */
async function getList() {
loadMoreState.value = 'loading'
try {
const params: Record<string, any> = { ...queryParams.value }
if (searchForm.productId) {
params.productIds = [searchForm.productId]
}
if (searchForm.warehouseId) {
params.warehouseIds = [searchForm.warehouseId]
}
const data = await getStockPage(params)
list.value = [...list.value, ...data.list]
total.value = data.total
loadMoreState.value = list.value.length >= total.value ? 'finished' : 'loading'
} catch {
queryParams.value.pageNo = queryParams.value.pageNo > 1 ? queryParams.value.pageNo - 1 : 1
loadMoreState.value = 'error'
}
}
/** 搜索 */
function handleSearch() {
searchVisible.value = false
queryParams.value = {
pageNo: 1,
pageSize: queryParams.value.pageSize,
}
list.value = []
getList()
}
/** 重置 */
function handleReset() {
searchForm.productId = undefined
searchForm.warehouseId = undefined
searchVisible.value = false
queryParams.value = { pageNo: 1, pageSize: 10 }
list.value = []
getList()
}
/** 加载更多 */
function loadMore() {
if (loadMoreState.value === 'finished') return
queryParams.value.pageNo++
getList()
}
/** 触底加载更多 */
onReachBottom(() => {
loadMore()
})
/** 初始化 */
onMounted(async () => {
getList()
// 加载仓库列表
warehouseList.value = await getWarehouseSimpleList()
})
</script>
<style lang="scss" scoped>
</style>