feat:模具管理-更换压网模块
parent
e3230555a0
commit
b78db18264
@ -0,0 +1,233 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<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>
|
||||
<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">
|
||||
<view class="list-wrap">
|
||||
<view v-for="item in list" :key="item.id" class="record-card">
|
||||
<view class="record-header">
|
||||
<text class="record-title">{{ item.moldName || '-' }}</text>
|
||||
<text class="record-time">{{ formatDateTime(item.pressureNetTime) }}</text>
|
||||
</view>
|
||||
<view class="record-body">
|
||||
<view class="record-row">
|
||||
<text class="record-label">{{ t('moldPressureNet.moldGroup') }}</text>
|
||||
<text class="record-value">{{ item.moldBrandName || '-' }}</text>
|
||||
</view>
|
||||
<view class="record-row">
|
||||
<text class="record-label">{{ t('moldPressureNet.createTime') }}</text>
|
||||
<text class="record-value">{{ formatDateTime(item.createTime) }}</text>
|
||||
</view>
|
||||
<view class="record-row">
|
||||
<text class="record-label">{{ t('moldPressureNet.remark') }}</text>
|
||||
<text class="record-value">{{ item.remark || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="loading && pageNo === 1" class="hint">{{ t('functionCommon.loading') }}</view>
|
||||
<view v-else-if="!list.length" class="hint">{{ t('moldPressureNet.noHistory') }}</view>
|
||||
<view v-else-if="loadingMore" class="hint">{{ t('functionCommon.loadingMore') }}</view>
|
||||
<view v-else-if="finished" class="hint">{{ t('functionCommon.noMoreData') }}</view>
|
||||
</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>
|
||||
</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>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import NavBar from '@/components/common/NavBar.vue'
|
||||
import { getPressureNetRecordPage } from '@/api/mes/mold'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const list = ref([])
|
||||
const loading = ref(false)
|
||||
const loadingMore = ref(false)
|
||||
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('')
|
||||
|
||||
onLoad(() => {
|
||||
fetchList(true)
|
||||
})
|
||||
|
||||
onReachBottom(() => {
|
||||
loadMore()
|
||||
})
|
||||
|
||||
function normalizePageData(res) {
|
||||
const root = res && res.data !== undefined ? res.data : res
|
||||
const rows = root?.list || root?.rows || root?.records || root?.data?.list || root?.data?.rows || []
|
||||
const total = root?.total ?? root?.data?.total ?? (Array.isArray(rows) ? rows.length : 0)
|
||||
return {
|
||||
list: Array.isArray(rows) ? rows : [],
|
||||
total: Number(total || 0)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchList(reset) {
|
||||
if (reset) {
|
||||
pageNo.value = 1
|
||||
finished.value = false
|
||||
}
|
||||
if (pageNo.value === 1) {
|
||||
loading.value = true
|
||||
} else {
|
||||
loadingMore.value = true
|
||||
}
|
||||
try {
|
||||
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
|
||||
const res = await getPressureNetRecordPage(params)
|
||||
const page = normalizePageData(res)
|
||||
list.value = reset ? page.list : [...list.value, ...page.list]
|
||||
finished.value = list.value.length >= page.total || page.list.length < pageSize.value
|
||||
} catch (error) {
|
||||
if (!reset) pageNo.value = Math.max(1, pageNo.value - 1)
|
||||
uni.showToast({ title: t('functionCommon.loadFailed'), icon: 'none' })
|
||||
} finally {
|
||||
loading.value = false
|
||||
loadingMore.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMore() {
|
||||
if (loading.value || loadingMore.value || finished.value) return
|
||||
pageNo.value += 1
|
||||
await fetchList(false)
|
||||
}
|
||||
|
||||
function resetFilter() {
|
||||
brandNameKeyword.value = ''
|
||||
pressureNetTimeFilter.value = ''
|
||||
fetchList(true)
|
||||
}
|
||||
|
||||
// 时间筛选弹窗
|
||||
function openTimePicker() {
|
||||
tempDate.value = pressureNetTimeFilter.value || ''
|
||||
showTimePicker.value = true
|
||||
}
|
||||
|
||||
function closeTimePicker() {
|
||||
showTimePicker.value = false
|
||||
}
|
||||
|
||||
function onDateChange(event) {
|
||||
tempDate.value = event?.detail?.value || ''
|
||||
}
|
||||
|
||||
function confirmTimeFilter() {
|
||||
pressureNetTimeFilter.value = tempDate.value
|
||||
closeTimePicker()
|
||||
fetchList(true)
|
||||
}
|
||||
|
||||
function clearTimeFilter() {
|
||||
pressureNetTimeFilter.value = ''
|
||||
tempDate.value = ''
|
||||
closeTimePicker()
|
||||
fetchList(true)
|
||||
}
|
||||
|
||||
function formatDateTime(value) {
|
||||
if (!value) return '-'
|
||||
if (Array.isArray(value) && value.length >= 3) {
|
||||
const [year, month, day, hour = 0, minute = 0, second = 0] = value
|
||||
const pad = (num) => String(num).padStart(2, '0')
|
||||
return `${year}-${pad(month)}-${pad(day)} ${pad(hour)}:${pad(minute)}:${pad(second)}`
|
||||
}
|
||||
const date = new Date(value)
|
||||
if (Number.isNaN(date.getTime())) return String(value)
|
||||
const pad = (num) => String(num).padStart(2, '0')
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<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; }
|
||||
.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); }
|
||||
.record-header { display: flex; align-items: center; justify-content: space-between; gap: 16rpx; padding-bottom: 18rpx; border-bottom: 1rpx solid #eef2f7; }
|
||||
.record-title { font-size: 32rpx; font-weight: 700; color: #111827; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.record-time { flex-shrink: 0; font-size: 24rpx; color: #1f7cff; }
|
||||
.record-body { margin-top: 16rpx; display: flex; flex-direction: column; gap: 12rpx; }
|
||||
.record-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 20rpx; }
|
||||
.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>
|
||||
Loading…
Reference in New Issue