style:压网历史,备件盘点,物料盘点-搜索框样式优化

master
zhongwenkai 19 hours ago
parent 29a9ffe2a5
commit 93658fce9a

@ -3,23 +3,32 @@
<NavBar :title="'物料盘点'" />
<view class="filter-bar">
<view class="keyword-box">
<input
v-model="searchKeyword"
class="keyword-input"
placeholder="搜索单号"
confirm-type="search"
@input="handleKeywordInput"
@confirm="handleSearch"
/>
</view>
<picker mode="selector" :range="statusLabels" :value="statusIndex" @change="onStatusChange">
<view class="status-box">
<text class="status-box-text">{{ currentStatusLabel }}</text>
<uni-icons type="bottom" size="14" color="#9ca3af"></uni-icons>
<view class="filter-row search-row">
<view class="keyword-wrap">
<input
v-model="searchKeyword"
class="keyword-input"
placeholder="搜索单号"
confirm-type="search"
@input="handleKeywordInput"
@confirm="handleSearch"
/>
</view>
<view class="icon-filter-btn" @click="resetFilters">
<uni-icons type="refresh" size="24" color="#7b8491"></uni-icons>
</view>
<view class="icon-filter-btn" @click="openFilterDrawer">
<uni-icons type="settings" size="24" color="#7b8491"></uni-icons>
</view>
</picker>
<view class="reset-filter-btn" @click="resetFilters"></view>
</view>
<view class="filter-row quick-row">
<picker mode="selector" :range="statusLabels" :value="statusIndex" @change="onStatusChange">
<view class="status-filter">
<text :class="['status-filter-text', selectedStatus === '' ? 'placeholder' : '']">{{ currentStatusLabel }}</text>
<uni-icons type="bottom" size="14" color="#a8adb7"></uni-icons>
</view>
</picker>
</view>
</view>
<scroll-view
@ -94,6 +103,30 @@
</view>
</scroll-view>
<!-- 筛选抽屉 -->
<uni-popup ref="filterPopupRef" class="material-check-filter-popup" type="right" background-color="transparent" :animation="false">
<view class="filter-drawer">
<view class="drawer-header">
<text class="drawer-title">更多筛选</text>
</view>
<scroll-view scroll-y class="drawer-body">
<view class="drawer-section drawer-fields">
<view class="drawer-field">
<text class="drawer-label">盘点时间</text>
<view class="drawer-date">
<uni-datetime-picker v-model="checkTimeFilter" type="daterange" :clear-icon="true"
start-placeholder="开始时间" end-placeholder="结束时间" />
</view>
</view>
</view>
</scroll-view>
<view class="drawer-actions">
<view class="drawer-action reset" @click="resetFilters"></view>
<view class="drawer-action confirm" @click="confirmFilterDrawer"></view>
</view>
</view>
</uni-popup>
<view v-if="showGoTop" class="go-top-btn" @click="goTop">
<uni-icons type="arrow-up" size="20" color="#1f4b79"></uni-icons>
</view>
@ -152,14 +185,15 @@ import { DICT_TYPE, useDict } from '@/utils/dict'
const selectedStatus = ref('')
const searchKeyword = ref('')
const materialWarehouseId = ref('')
const checkTimeFilter = ref([])
const statusOptions = computed(() => {
const dictOptions = (erp_audit_status.value || [])
.filter((item) => item?.label !== undefined && item?.value !== undefined)
.map((item) => ({ ...item, value: String(item.value) }))
if (dictOptions.length) return [{ label: '全部', value: '' }, ...dictOptions]
if (dictOptions.length) return [{ label: '盘点状态', value: '' }, ...dictOptions]
return [
{ label: '全部', value: '' },
{ label: '盘点状态', value: '' },
{ label: '待提交', value: '0' },
{ label: '审核中', value: '10' },
{ label: '已通过', value: '20' },
@ -285,13 +319,15 @@ async function fetchList(reset) {
loadingMore.value = true
}
try {
const checkTimeRange = Array.isArray(checkTimeFilter.value) ? checkTimeFilter.value : []
const params = {
pageNo: pageNo.value,
pageSize: pageSize.value,
no: searchKeyword.value.trim() || undefined,
status: selectedStatus.value || undefined,
warehouseId: materialWarehouseId.value || undefined,
categoryType: 2
categoryType: 2,
checkTime: checkTimeRange.length === 2 ? [checkTimeRange[0] + ' 00:00:00', checkTimeRange[1] + ' 23:59:59'] : undefined
}
const res = await getMaterialCheckPage(params)
const page = normalizePageData(res)
@ -325,10 +361,27 @@ function handleKeywordInput() {
}, 300)
}
const filterPopupRef = ref(null)
function openFilterDrawer() {
filterPopupRef.value?.open()
}
function closeFilterDrawer() {
filterPopupRef.value?.close()
}
function confirmFilterDrawer() {
closeFilterDrawer()
fetchList(true)
}
function resetFilters() {
clearSearchTimer()
searchKeyword.value = ''
selectedStatus.value = ''
checkTimeFilter.value = []
filterPopupRef.value?.close()
fetchList(true)
}
@ -588,63 +641,236 @@ onUnload(() => {
}
.filter-bar {
padding: 18rpx 14rpx 20rpx;
background: #f3f4f6;
}
.filter-row {
display: flex;
align-items: center;
gap: 12rpx;
padding: 18rpx 24rpx;
background: #fff;
gap: 18rpx;
}
.keyword-box {
flex: 1;
.quick-row {
margin-top: 18rpx;
}
.quick-row > picker {
min-width: 0;
flex: 1;
}
.keyword-wrap,
.status-filter,
.icon-filter-btn {
height: 66rpx;
padding: 0 28rpx;
background: #f4f5f7;
border: 1rpx solid #e5e7eb;
border-radius: 12rpx;
border: 1rpx solid #d9dde5;
background: #ffffff;
box-sizing: border-box;
}
.keyword-wrap {
min-width: 0;
flex: 1;
display: flex;
align-items: center;
}
.keyword-input {
width: 100%;
font-size: 24rpx;
height: 64rpx;
padding: 0 20rpx;
font-size: 26rpx;
color: #374151;
}
.status-box {
flex-shrink: 0;
.status-filter {
min-width: 0;
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
height: 66rpx;
padding: 0 28rpx;
min-width: 160rpx;
background: #fff;
border: 1rpx solid #e5e7eb;
border-radius: 12rpx;
padding: 0 18rpx 0 26rpx;
}
.status-box-text {
font-size: 24rpx;
color: #374151;
min-width: 0;
.icon-filter-btn {
width: 66rpx;
flex: 0 0 66rpx;
display: flex;
align-items: center;
justify-content: center;
border-color: transparent;
background: transparent;
}
.status-filter-text {
min-width: 0rpx;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 26rpx;
color: #374151;
}
.reset-filter-btn {
height: 66rpx;
line-height: 66rpx;
padding: 0 28rpx;
.status-filter-text.placeholder {
color: #a8adb7;
}
/* ====== 筛选抽屉 ====== */
::deep(.material-check-filter-popup.right .uni-popup__content-transition) {
transform: none !important;
}
.filter-drawer {
width: 630rpx;
height: calc(100vh - var(--status-bar-height));
margin-top: var(--status-bar-height);
background: #f5f5f7;
display: flex;
flex-direction: column;
overflow: hidden;
border-radius: 28rpx 0 0 28rpx;
}
.drawer-header {
height: 104rpx;
padding: 18rpx 34rpx 0;
background: #ffffff;
display: flex;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
}
.drawer-title {
color: #1f2937;
font-size: 34rpx;
line-height: 1.3;
font-weight: 700;
}
.drawer-body {
flex: 1;
min-height: 0;
padding-bottom: 40rpx;
box-sizing: border-box;
}
.drawer-section {
margin-bottom: 18rpx;
padding: 8rpx 28rpx;
border-radius: 24rpx;
background: #ffffff;
box-sizing: border-box;
}
.drawer-fields {
display: flex;
flex-direction: column;
}
.drawer-field {
min-width: 0;
min-height: 98rpx;
display: flex;
align-items: center;
gap: 20rpx;
border-bottom: 1rpx solid #eceff3;
box-sizing: border-box;
}
.drawer-field:last-child {
border-bottom: 0;
}
.drawer-label {
width: 160rpx;
flex: 0 0 160rpx;
font-size: 24rpx;
line-height: 1.3;
color: #4b5563;
background: #fff;
border: 1rpx solid #e5e7eb;
border-radius: 12rpx;
flex-shrink: 0;
font-weight: 500;
}
.drawer-date {
min-width: 0;
flex: 1;
width: 100%;
min-height: 74rpx;
border: 0;
border-radius: 8rpx;
background: #f7f8fb;
box-sizing: border-box;
display: flex;
align-items: center;
padding: 0 12rpx;
}
.drawer-date :deep(.uni-date),
.drawer-date :deep(.uni-date-editor),
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
width: 100%;
}
.drawer-date :deep(.uni-date-editor),
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
min-height: 74rpx;
}
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
border: 0;
padding: 0;
background: transparent;
}
.drawer-date :deep(.uni-date-range) {
display: flex;
align-items: center;
}
.drawer-date :deep(.uni-date__x-input) {
text-align: center;
font-size: 26rpx;
color: #111827;
}
.drawer-actions {
height: 126rpx;
padding: 18rpx 28rpx 24rpx;
box-sizing: border-box;
display: flex;
align-items: center;
gap: 0;
background: #ffffff;
box-shadow: 0 -8rpx 24rpx rgba(17, 24, 39, 0.06);
}
.drawer-action {
flex: 1;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
font-weight: 600;
border: 2rpx solid #174b78;
box-sizing: border-box;
}
.drawer-action.reset {
border-radius: 12rpx 0 0 12rpx;
background: #ffffff;
color: #174b78;
}
.drawer-action.confirm {
border-radius: 0 12rpx 12rpx 0;
background: #174b78;
color: #ffffff;
}
.list-scroll {

@ -3,21 +3,23 @@
<NavBar :title="t('moldPressureNet.historyTitle')" />
<view class="filter-bar">
<view class="keyword-box">
<input
v-model="brandNameKeyword"
class="keyword-input"
:placeholder="t('moldPressureNet.searchBrandName')"
confirm-type="search"
@confirm="fetchList(true)"
/>
</view>
<view class="keyword-box time-box" @click="openTimePicker">
<text :class="pressureNetTimeFilter ? 'time-text' : 'time-placeholder'">{{ pressureNetTimeFilter || t('moldPressureNet.pressureNetTime') }}</text>
<uni-icons type="calendar" size="18" color="#9ca3af"></uni-icons>
<view class="filter-row search-row">
<view class="keyword-wrap">
<input
v-model="brandNameKeyword"
class="keyword-input"
:placeholder="t('moldPressureNet.searchBrandName')"
confirm-type="search"
@confirm="fetchList(true)"
/>
</view>
<view class="icon-filter-btn" @click="resetFilter">
<uni-icons type="refresh" size="24" color="#7b8491"></uni-icons>
</view>
<view class="icon-filter-btn" @click="openFilterDrawer">
<uni-icons type="settings" size="24" color="#7b8491"></uni-icons>
</view>
</view>
<view class="filter-btn" @click="fetchList(true)">{{ t('functionCommon.search') }}</view>
<view class="filter-btn" @click="resetFilter">{{ t('functionCommon.reset') }}</view>
</view>
<scroll-view scroll-y class="list-scroll" @scrolltolower="loadMore" :lower-threshold="80">
@ -50,26 +52,29 @@
</view>
</scroll-view>
<!-- 压网时间筛选弹窗 -->
<view v-if="showTimePicker" class="picker-mask" @click="closeTimePicker">
<view class="picker-popup" @click.stop>
<view class="picker-header">
<text class="picker-title">{{ t('moldPressureNet.pressureNetTime') }}</text>
<view class="picker-close" @click="closeTimePicker">
<uni-icons type="close" size="24" color="#6b7280"></uni-icons>
</view>
<!-- 筛选抽屉 -->
<uni-popup ref="filterPopupRef" class="pressure-net-filter-popup" type="right" background-color="transparent" :animation="false">
<view class="filter-drawer">
<view class="drawer-header">
<text class="drawer-title">更多筛选</text>
</view>
<view class="picker-body">
<picker mode="date" :value="tempDate" @change="onDateChange">
<view class="time-field">{{ tempDate || $t('moldPressureNet.selectDate') }}</view>
</picker>
</view>
<view class="picker-footer-bar">
<view class="picker-footer-btn secondary" @click="clearTimeFilter">{{ $t('functionCommon.clear') }}</view>
<view class="picker-footer-btn primary" @click="confirmTimeFilter">{{ $t('common.complete') }}</view>
<scroll-view scroll-y class="drawer-body">
<view class="drawer-section drawer-fields">
<view class="drawer-field">
<text class="drawer-label">{{ t('moldPressureNet.pressureNetTime') }}</text>
<view class="drawer-date">
<uni-datetime-picker v-model="pressureNetTimeFilter" type="daterange" :clear-icon="true"
start-placeholder="开始时间" end-placeholder="结束时间" />
</view>
</view>
</view>
</scroll-view>
<view class="drawer-actions">
<view class="drawer-action reset" @click="resetFilter">{{ t('functionCommon.reset') }}</view>
<view class="drawer-action confirm" @click="confirmFilterDrawer">{{ t('functionCommon.confirm') }}</view>
</view>
</view>
</view>
</uni-popup>
</view>
</template>
@ -89,11 +94,8 @@ const finished = ref(false)
const pageNo = ref(1)
const pageSize = ref(10)
const brandNameKeyword = ref('')
const pressureNetTimeFilter = ref('')
//
const showTimePicker = ref(false)
const tempDate = ref('')
const pressureNetTimeFilter = ref([])
const filterPopupRef = ref(null)
onLoad(() => {
fetchList(true)
@ -124,14 +126,17 @@ async function fetchList(reset) {
loadingMore.value = true
}
try {
const timeRange = Array.isArray(pressureNetTimeFilter.value) ? pressureNetTimeFilter.value : []
const params = {
pageNo: pageNo.value,
pageSize: pageSize.value
}
const brandName = brandNameKeyword.value.trim()
if (brandName) params.moldBrandName = brandName
const timeVal = pressureNetTimeFilter.value.trim()
if (timeVal) params.pressureNetTime = timeVal
if (timeRange.length === 2) {
params['pressureNetTime[0]'] = timeRange[0] + ' 00:00:00'
params['pressureNetTime[1]'] = timeRange[1] + ' 23:59:59'
}
const res = await getPressureNetRecordPage(params)
const page = normalizePageData(res)
list.value = reset ? page.list : [...list.value, ...page.list]
@ -151,36 +156,23 @@ async function loadMore() {
await fetchList(false)
}
function resetFilter() {
brandNameKeyword.value = ''
pressureNetTimeFilter.value = ''
fetchList(true)
function openFilterDrawer() {
filterPopupRef.value?.open()
}
//
function openTimePicker() {
tempDate.value = pressureNetTimeFilter.value || ''
showTimePicker.value = true
function closeFilterDrawer() {
filterPopupRef.value?.close()
}
function closeTimePicker() {
showTimePicker.value = false
}
function onDateChange(event) {
tempDate.value = event?.detail?.value || ''
}
function confirmTimeFilter() {
pressureNetTimeFilter.value = tempDate.value
closeTimePicker()
function confirmFilterDrawer() {
closeFilterDrawer()
fetchList(true)
}
function clearTimeFilter() {
pressureNetTimeFilter.value = ''
tempDate.value = ''
closeTimePicker()
function resetFilter() {
brandNameKeyword.value = ''
pressureNetTimeFilter.value = []
filterPopupRef.value?.close()
fetchList(true)
}
@ -200,14 +192,206 @@ function formatDateTime(value) {
<style lang="scss" scoped>
.page-container { min-height: 100vh; background: #f5f7fb; }
.filter-bar { display: flex; align-items: center; gap: 12rpx; padding: 18rpx 24rpx 0; flex-wrap: wrap; }
.keyword-box, .filter-btn { height: 66rpx; background: #ffffff; border: 1rpx solid #d9dde5; box-sizing: border-box; display: flex; align-items: center; }
.keyword-box { flex: 1; min-width: 200rpx; padding: 0 20rpx; }
.keyword-input { width: 100%; font-size: 24rpx; color: #374151; }
.time-box { justify-content: space-between; min-width: 220rpx; }
.time-text { font-size: 24rpx; color: #374151; }
.time-placeholder { font-size: 24rpx; color: #9ca3af; }
.filter-btn { flex-shrink: 0; justify-content: center; min-width: 104rpx; padding: 0 18rpx; font-size: 24rpx; color: #4b5563; }
.filter-bar {
padding: 18rpx 14rpx 20rpx;
background: #f3f4f6;
}
.filter-row {
display: flex;
align-items: center;
gap: 18rpx;
}
.keyword-wrap,
.icon-filter-btn {
height: 66rpx;
border: 1rpx solid #d9dde5;
background: #ffffff;
box-sizing: border-box;
}
.keyword-wrap {
min-width: 0;
flex: 1;
display: flex;
align-items: center;
}
.keyword-input {
width: 100%;
height: 64rpx;
padding: 0 20rpx;
font-size: 26rpx;
color: #374151;
}
.icon-filter-btn {
width: 66rpx;
flex: 0 0 66rpx;
display: flex;
align-items: center;
justify-content: center;
border-color: transparent;
background: transparent;
}
::deep(.pressure-net-filter-popup.right .uni-popup__content-transition) {
transform: none !important;
}
.filter-drawer {
width: 630rpx;
height: calc(100vh - var(--status-bar-height));
margin-top: var(--status-bar-height);
background: #f5f5f7;
display: flex;
flex-direction: column;
overflow: hidden;
border-radius: 28rpx 0 0 28rpx;
}
.drawer-header {
height: 104rpx;
padding: 18rpx 34rpx 0;
background: #ffffff;
display: flex;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
}
.drawer-title {
color: #1f2937;
font-size: 34rpx;
line-height: 1.3;
font-weight: 700;
}
.drawer-body {
flex: 1;
min-height: 0;
padding-bottom: 40rpx;
box-sizing: border-box;
}
.drawer-section {
margin-bottom: 18rpx;
padding: 8rpx 28rpx;
border-radius: 24rpx;
background: #ffffff;
box-sizing: border-box;
}
.drawer-fields {
display: flex;
flex-direction: column;
}
.drawer-field {
min-width: 0;
min-height: 98rpx;
display: flex;
align-items: center;
gap: 20rpx;
border-bottom: 1rpx solid #eceff3;
box-sizing: border-box;
}
.drawer-field:last-child {
border-bottom: 0;
}
.drawer-label {
width: 160rpx;
flex: 0 0 160rpx;
font-size: 24rpx;
line-height: 1.3;
color: #4b5563;
font-weight: 500;
}
.drawer-date {
min-width: 0;
flex: 1;
width: 100%;
min-height: 74rpx;
border: 0;
border-radius: 8rpx;
background: #f7f8fb;
box-sizing: border-box;
display: flex;
align-items: center;
padding: 0 12rpx;
}
.drawer-date :deep(.uni-date),
.drawer-date :deep(.uni-date-editor),
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
width: 100%;
}
.drawer-date :deep(.uni-date-editor),
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
min-height: 74rpx;
}
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
border: 0;
padding: 0;
background: transparent;
}
.drawer-date :deep(.uni-date-range) {
display: flex;
align-items: center;
}
.drawer-date :deep(.uni-date__x-input) {
text-align: center;
font-size: 26rpx;
color: #111827;
}
.drawer-actions {
height: 126rpx;
padding: 18rpx 28rpx 24rpx;
box-sizing: border-box;
display: flex;
align-items: center;
gap: 0;
background: #ffffff;
box-shadow: 0 -8rpx 24rpx rgba(17, 24, 39, 0.06);
}
.drawer-action {
flex: 1;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
font-weight: 600;
border: 2rpx solid #174b78;
box-sizing: border-box;
}
.drawer-action.reset {
border-radius: 12rpx 0 0 12rpx;
background: #ffffff;
color: #174b78;
}
.drawer-action.confirm {
border-radius: 0 12rpx 12rpx 0;
background: #174b78;
color: #ffffff;
}
.list-scroll { height: calc(100vh - 170rpx); }
.list-wrap { padding: 4rpx 24rpx 40rpx; }
.record-card { margin-top: 20rpx; padding: 24rpx; border-radius: 16rpx; background: #ffffff; box-shadow: 0 8rpx 24rpx rgba(15, 23, 42, 0.06); }
@ -219,15 +403,5 @@ function formatDateTime(value) {
.record-label { width: 150rpx; flex-shrink: 0; font-size: 26rpx; color: #8a94a6; }
.record-value { flex: 1; text-align: right; font-size: 27rpx; color: #374151; line-height: 1.5; word-break: break-all; }
.hint { padding: 40rpx 0; text-align: center; color: #9ca3af; font-size: 26rpx; }
.picker-mask { position: fixed; left: 0; right: 0; top: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 100; display: flex; align-items: flex-end; }
.picker-popup { width: 100%; background: #ffffff; border-radius: 24rpx 24rpx 0 0; padding-bottom: env(safe-area-inset-bottom); }
.picker-header { display: flex; align-items: center; justify-content: space-between; padding: 28rpx 32rpx; border-bottom: 1rpx solid #e5e7eb; }
.picker-title { font-size: 34rpx; font-weight: 600; color: #1f2937; }
.picker-close { width: 48rpx; height: 48rpx; display: flex; align-items: center; justify-content: center; }
.picker-body { padding: 32rpx; }
.time-field { height: 80rpx; display: flex; align-items: center; justify-content: center; background: #f8fafc; border: 1rpx solid #e5e7eb; border-radius: 12rpx; font-size: 28rpx; color: #374151; }
.picker-footer-bar { display: flex; gap: 16rpx; padding: 16rpx 32rpx 24rpx; }
.picker-footer-btn { flex: 1; height: 80rpx; border-radius: 12rpx; display: flex; align-items: center; justify-content: center; font-size: 28rpx; font-weight: 600; }
.picker-footer-btn.secondary { background: #f3f4f6; color: #6b7280; }
.picker-footer-btn.primary { background: linear-gradient(135deg, #1f7cff, #3b82f6); color: #ffffff; }
</style>

@ -2,25 +2,33 @@
<view class="page-container">
<NavBar :title="'备件盘点'" />
<!-- 搜索栏 -->
<view class="filter-bar">
<view class="keyword-box">
<input
v-model="searchKeyword"
class="keyword-input"
placeholder="搜索单号"
confirm-type="search"
@input="handleKeywordInput"
@confirm="handleSearch"
/>
</view>
<picker mode="selector" :range="statusLabels" :value="statusIndex" @change="onStatusChange">
<view class="status-box">
<text class="status-box-text">{{ currentStatusLabel }}</text>
<uni-icons type="bottom" size="14" color="#9ca3af"></uni-icons>
<view class="filter-row search-row">
<view class="keyword-wrap">
<input
v-model="searchKeyword"
class="keyword-input"
placeholder="搜索单号"
confirm-type="search"
@input="handleKeywordInput"
@confirm="handleSearch"
/>
</view>
<view class="icon-filter-btn" @click="resetFilters">
<uni-icons type="refresh" size="24" color="#7b8491"></uni-icons>
</view>
<view class="icon-filter-btn" @click="openFilterDrawer">
<uni-icons type="settings" size="24" color="#7b8491"></uni-icons>
</view>
</picker>
<view class="reset-filter-btn" @click="resetFilters"></view>
</view>
<view class="filter-row quick-row">
<picker mode="selector" :range="statusLabels" :value="statusIndex" @change="onStatusChange">
<view class="status-filter">
<text :class="['status-filter-text', selectedStatus === '' ? 'placeholder' : '']">{{ currentStatusLabel }}</text>
<uni-icons type="bottom" size="14" color="#a8adb7"></uni-icons>
</view>
</picker>
</view>
</view>
<!-- 列表 -->
@ -101,6 +109,30 @@
</view>
</scroll-view>
<!-- 筛选抽屉 -->
<uni-popup ref="filterPopupRef" class="sparepart-check-filter-popup" type="right" background-color="transparent" :animation="false">
<view class="filter-drawer">
<view class="drawer-header">
<text class="drawer-title">更多筛选</text>
</view>
<scroll-view scroll-y class="drawer-body">
<view class="drawer-section drawer-fields">
<view class="drawer-field">
<text class="drawer-label">盘点时间</text>
<view class="drawer-date">
<uni-datetime-picker v-model="checkTimeFilter" type="daterange" :clear-icon="true"
start-placeholder="开始时间" end-placeholder="结束时间" />
</view>
</view>
</view>
</scroll-view>
<view class="drawer-actions">
<view class="drawer-action reset" @click="resetFilters"></view>
<view class="drawer-action confirm" @click="confirmFilterDrawer"></view>
</view>
</view>
</uni-popup>
<!-- 回顶部 -->
<view v-if="showGoTop" class="go-top-btn" @click="goTop">
<uni-icons type="arrow-up" size="20" color="#1f4b79"></uni-icons>
@ -161,14 +193,15 @@ import { DICT_TYPE, useDict } from '@/utils/dict'
const selectedStatus = ref('')
const searchKeyword = ref('')
const sparepartWarehouseId = ref('')
const checkTimeFilter = ref([])
const statusOptions = computed(() => {
const dictOptions = (erp_audit_status.value || [])
.filter((item) => item?.label !== undefined && item?.value !== undefined)
.map((item) => ({ ...item, value: String(item.value) }))
if (dictOptions.length) return [{ label: '全部', value: '' }, ...dictOptions]
if (dictOptions.length) return [{ label: '盘点状态', value: '' }, ...dictOptions]
return [
{ label: '全部', value: '' },
{ label: '盘点状态', value: '' },
{ label: '待提交', value: '0' },
{ label: '审核中', value: '10' },
{ label: '已通过', value: '20' },
@ -294,12 +327,14 @@ async function fetchList(reset) {
loadingMore.value = true
}
try {
const checkTimeRange = Array.isArray(checkTimeFilter.value) ? checkTimeFilter.value : []
const params = {
pageNo: pageNo.value,
pageSize: pageSize.value,
no: searchKeyword.value.trim() || undefined,
status: selectedStatus.value || undefined,
warehouseId: sparepartWarehouseId.value || undefined
warehouseId: sparepartWarehouseId.value || undefined,
checkTime: checkTimeRange.length === 2 ? [checkTimeRange[0] + ' 00:00:00', checkTimeRange[1] + ' 23:59:59'] : undefined
}
const res = await getSparepartCheckPage(params)
const page = normalizePageData(res)
@ -333,10 +368,27 @@ function handleKeywordInput() {
}, 300)
}
const filterPopupRef = ref(null)
function openFilterDrawer() {
filterPopupRef.value?.open()
}
function closeFilterDrawer() {
filterPopupRef.value?.close()
}
function confirmFilterDrawer() {
closeFilterDrawer()
fetchList(true)
}
function resetFilters() {
clearSearchTimer()
searchKeyword.value = ''
selectedStatus.value = ''
checkTimeFilter.value = []
filterPopupRef.value?.close()
fetchList(true)
}
@ -621,63 +673,236 @@ onUnload(() => {
/* ====== 搜索栏 ====== */
.filter-bar {
padding: 18rpx 14rpx 20rpx;
background: #f3f4f6;
}
.filter-row {
display: flex;
align-items: center;
gap: 12rpx;
padding: 18rpx 24rpx;
background: #fff;
gap: 18rpx;
}
.keyword-box {
flex: 1;
.quick-row {
margin-top: 18rpx;
}
.quick-row > picker {
min-width: 0;
flex: 1;
}
.keyword-wrap,
.status-filter,
.icon-filter-btn {
height: 66rpx;
padding: 0 28rpx;
background: #f4f5f7;
border: 1rpx solid #e5e7eb;
border-radius: 12rpx;
border: 1rpx solid #d9dde5;
background: #ffffff;
box-sizing: border-box;
}
.keyword-wrap {
min-width: 0;
flex: 1;
display: flex;
align-items: center;
}
.keyword-input {
width: 100%;
font-size: 24rpx;
height: 64rpx;
padding: 0 20rpx;
font-size: 26rpx;
color: #374151;
}
.status-box {
flex-shrink: 0;
.status-filter {
min-width: 0;
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
height: 66rpx;
padding: 0 28rpx;
min-width: 160rpx;
background: #fff;
border: 1rpx solid #e5e7eb;
border-radius: 12rpx;
padding: 0 18rpx 0 26rpx;
}
.status-box-text {
font-size: 24rpx;
color: #374151;
min-width: 0;
.icon-filter-btn {
width: 66rpx;
flex: 0 0 66rpx;
display: flex;
align-items: center;
justify-content: center;
border-color: transparent;
background: transparent;
}
.status-filter-text {
min-width: 0rpx;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 26rpx;
color: #374151;
}
.reset-filter-btn {
height: 66rpx;
line-height: 66rpx;
padding: 0 28rpx;
.status-filter-text.placeholder {
color: #a8adb7;
}
/* ====== 筛选抽屉 ====== */
::deep(.sparepart-check-filter-popup.right .uni-popup__content-transition) {
transform: none !important;
}
.filter-drawer {
width: 630rpx;
height: calc(100vh - var(--status-bar-height));
margin-top: var(--status-bar-height);
background: #f5f5f7;
display: flex;
flex-direction: column;
overflow: hidden;
border-radius: 28rpx 0 0 28rpx;
}
.drawer-header {
height: 104rpx;
padding: 18rpx 34rpx 0;
background: #ffffff;
display: flex;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
}
.drawer-title {
color: #1f2937;
font-size: 34rpx;
line-height: 1.3;
font-weight: 700;
}
.drawer-body {
flex: 1;
min-height: 0;
padding-bottom: 40rpx;
box-sizing: border-box;
}
.drawer-actions {
height: 126rpx;
padding: 18rpx 28rpx 24rpx;
box-sizing: border-box;
display: flex;
align-items: center;
gap: 0;
background: #ffffff;
box-shadow: 0 -8rpx 24rpx rgba(17, 24, 39, 0.06);
}
.drawer-action {
flex: 1;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
font-weight: 600;
border: 2rpx solid #174b78;
box-sizing: border-box;
}
.drawer-action.reset {
border-radius: 12rpx 0 0 12rpx;
background: #ffffff;
color: #174b78;
}
.drawer-action.confirm {
border-radius: 0 12rpx 12rpx 0;
background: #174b78;
color: #ffffff;
}
.drawer-section {
margin-bottom: 18rpx;
padding: 8rpx 28rpx;
border-radius: 24rpx;
background: #ffffff;
box-sizing: border-box;
}
.drawer-fields {
display: flex;
flex-direction: column;
}
.drawer-field {
min-width: 0;
min-height: 98rpx;
display: flex;
align-items: center;
gap: 20rpx;
border-bottom: 1rpx solid #eceff3;
box-sizing: border-box;
}
.drawer-field:last-child {
border-bottom: 0;
}
.drawer-label {
width: 160rpx;
flex: 0 0 160rpx;
font-size: 24rpx;
line-height: 1.3;
color: #4b5563;
background: #fff;
border: 1rpx solid #e5e7eb;
border-radius: 12rpx;
flex-shrink: 0;
font-weight: 500;
}
.drawer-date {
min-width: 0;
flex: 1;
width: 100%;
min-height: 74rpx;
border: 0;
border-radius: 8rpx;
background: #f7f8fb;
box-sizing: border-box;
display: flex;
align-items: center;
padding: 0 12rpx;
}
.drawer-date :deep(.uni-date),
.drawer-date :deep(.uni-date-editor),
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
width: 100%;
}
.drawer-date :deep(.uni-date-editor),
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
min-height: 74rpx;
}
.drawer-date :deep(.uni-date-editor--x),
.drawer-date :deep(.uni-date-x) {
border: 0;
padding: 0;
background: transparent;
}
.drawer-date :deep(.uni-date-range) {
display: flex;
align-items: center;
}
.drawer-date :deep(.uni-date__x-input) {
text-align: center;
font-size: 26rpx;
color: #111827;
}
/* ====== 列表 ====== */

Loading…
Cancel
Save