|
|
|
|
@ -2,29 +2,32 @@
|
|
|
|
|
<view class="page-container">
|
|
|
|
|
<NavBar :title="t('equipmentInspectionRecord.moduleName')" />
|
|
|
|
|
|
|
|
|
|
<view class="search-card">
|
|
|
|
|
<view class="search-row">
|
|
|
|
|
<view class="search-input-wrap">
|
|
|
|
|
<text class="iconfont icon-search search-icon"></text>
|
|
|
|
|
<input
|
|
|
|
|
v-model="searchKeyword"
|
|
|
|
|
class="search-input"
|
|
|
|
|
:placeholder="t('equipmentInspectionRecord.searchPlaceholder')"
|
|
|
|
|
confirm-type="search"
|
|
|
|
|
@confirm="handleSearch"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="search-btn" @click="handleSearch">{{ t('functionCommon.search') }}</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="filter-row">
|
|
|
|
|
<picker mode="selector" :range="taskTypeLabels" :value="taskTypeIndex" @change="onTaskTypeChange">
|
|
|
|
|
<view class="picker-chip">{{ currentTaskTypeLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
<picker mode="selector" :range="jobStatusLabels" :value="jobStatusIndex" @change="onJobStatusChange">
|
|
|
|
|
<view class="picker-chip">{{ currentJobStatusLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
<view class="reset-btn" @click="resetFilters">{{ t('functionCommon.reset') }}</view>
|
|
|
|
|
<view class="filter-bar">
|
|
|
|
|
<view class="keyword-box">
|
|
|
|
|
<input
|
|
|
|
|
v-model="searchKeyword"
|
|
|
|
|
class="keyword-input"
|
|
|
|
|
:placeholder="t('equipmentInspectionRecord.searchPlaceholder')"
|
|
|
|
|
:focus="keywordFocus"
|
|
|
|
|
confirm-type="search"
|
|
|
|
|
@blur="keywordFocus = false"
|
|
|
|
|
@input="handleKeywordInput"
|
|
|
|
|
@confirm="handleSearch"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<picker mode="selector" :range="taskTypeLabels" :value="taskTypeIndex" @change="onTaskTypeChange">
|
|
|
|
|
<view class="status-box">
|
|
|
|
|
<text class="status-box-text">{{ currentTaskTypeLabel }}</text>
|
|
|
|
|
<uni-icons type="bottom" size="14" color="#9ca3af"></uni-icons>
|
|
|
|
|
</view>
|
|
|
|
|
</picker>
|
|
|
|
|
<picker mode="selector" :range="jobStatusLabels" :value="jobStatusIndex" @change="onJobStatusChange">
|
|
|
|
|
<view class="status-box">
|
|
|
|
|
<text class="status-box-text">{{ currentJobStatusLabel }}</text>
|
|
|
|
|
<uni-icons type="bottom" size="14" color="#9ca3af"></uni-icons>
|
|
|
|
|
</view>
|
|
|
|
|
</picker>
|
|
|
|
|
<view class="reset-filter-btn" @click="resetFilters">{{ t('functionCommon.reset') }}</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<scroll-view scroll-y class="list-scroll" :scroll-top="scrollTop" @scroll="onScroll" @scrolltolower="loadMore" :lower-threshold="80">
|
|
|
|
|
@ -75,7 +78,7 @@
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { computed, nextTick, ref } from 'vue'
|
|
|
|
|
import { onLoad, onReachBottom } from '@dcloudio/uni-app'
|
|
|
|
|
import { onLoad, onReachBottom, onShow, onUnload } from '@dcloudio/uni-app'
|
|
|
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
|
import NavBar from '@/components/common/NavBar.vue'
|
|
|
|
|
import { getEquipmentInspectionRecordPage } from '@/api/mes/equipmentInspectionRecord'
|
|
|
|
|
@ -94,6 +97,9 @@ const pageNo = ref(1)
|
|
|
|
|
const pageSize = ref(10)
|
|
|
|
|
const scrollTop = ref(0)
|
|
|
|
|
const showGoTop = ref(false)
|
|
|
|
|
const keywordFocus = ref(false)
|
|
|
|
|
|
|
|
|
|
let searchTimer = null
|
|
|
|
|
|
|
|
|
|
const taskTypeOptions = computed(() => [
|
|
|
|
|
{ label: t('functionCommon.all'), value: '' },
|
|
|
|
|
@ -130,10 +136,19 @@ const currentJobStatusLabel = computed(() => {
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onLoad(async () => {
|
|
|
|
|
activateKeywordFocus()
|
|
|
|
|
await initAllDict()
|
|
|
|
|
await fetchList(true)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onShow(() => {
|
|
|
|
|
activateKeywordFocus()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onUnload(() => {
|
|
|
|
|
clearSearchTimer()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onReachBottom(() => {
|
|
|
|
|
loadMore()
|
|
|
|
|
})
|
|
|
|
|
@ -182,14 +197,24 @@ function normalizePageData(res) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleSearch() {
|
|
|
|
|
clearSearchTimer()
|
|
|
|
|
uni.hideKeyboard()
|
|
|
|
|
fetchList(true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleKeywordInput() {
|
|
|
|
|
clearSearchTimer()
|
|
|
|
|
searchTimer = setTimeout(() => {
|
|
|
|
|
fetchList(true)
|
|
|
|
|
}, 300)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function resetFilters() {
|
|
|
|
|
clearSearchTimer()
|
|
|
|
|
searchKeyword.value = ''
|
|
|
|
|
selectedTaskType.value = ''
|
|
|
|
|
selectedJobStatus.value = ''
|
|
|
|
|
activateKeywordFocus()
|
|
|
|
|
await nextTick()
|
|
|
|
|
await fetchList(true)
|
|
|
|
|
}
|
|
|
|
|
@ -231,6 +256,20 @@ function goTop() {
|
|
|
|
|
scrollTop.value = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function activateKeywordFocus() {
|
|
|
|
|
keywordFocus.value = false
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
keywordFocus.value = true
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearSearchTimer() {
|
|
|
|
|
if (searchTimer) {
|
|
|
|
|
clearTimeout(searchTimer)
|
|
|
|
|
searchTimer = null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function taskTypeText(value) {
|
|
|
|
|
const normalized = String(value)
|
|
|
|
|
if (normalized === '1') return t('equipmentInspectionRecord.taskTypeInspect')
|
|
|
|
|
@ -289,17 +328,49 @@ function formatDateTime(value) {
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.page-container { min-height: 100vh; background: #f4f5f7; }
|
|
|
|
|
.search-card { margin: 20rpx 24rpx 0; padding: 24rpx; background: #fff; border-radius: 20rpx; }
|
|
|
|
|
.search-row { display: flex; gap: 16rpx; align-items: center; }
|
|
|
|
|
.search-input-wrap { flex: 1; display: flex; align-items: center; gap: 12rpx; padding: 0 20rpx; min-height: 84rpx; background: #f8fafc; border-radius: 16rpx; }
|
|
|
|
|
.search-icon { color: #94a3b8; font-size: 30rpx; }
|
|
|
|
|
.search-input { flex: 1; font-size: 28rpx; color: #111827; }
|
|
|
|
|
.search-btn, .reset-btn { min-width: 120rpx; height: 84rpx; border-radius: 16rpx; display: flex; align-items: center; justify-content: center; font-size: 28rpx; font-weight: 600; }
|
|
|
|
|
.search-btn { background: #1f4b79; color: #fff; }
|
|
|
|
|
.filter-row { display: flex; gap: 16rpx; margin-top: 16rpx; flex-wrap: wrap; }
|
|
|
|
|
.picker-chip { min-width: 220rpx; padding: 0 20rpx; height: 72rpx; background: #eef4fb; border-radius: 14rpx; color: #1f4b79; font-size: 26rpx; display: flex; align-items: center; }
|
|
|
|
|
.reset-btn { background: #eef2f7; color: #475569; height: 72rpx; }
|
|
|
|
|
.list-scroll { height: calc(100vh - 304rpx); }
|
|
|
|
|
.filter-bar {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: minmax(0, 0.9fr) 136rpx 136rpx 88rpx;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 10rpx;
|
|
|
|
|
padding: 18rpx 20rpx 20rpx;
|
|
|
|
|
}
|
|
|
|
|
.keyword-box,
|
|
|
|
|
.status-box,
|
|
|
|
|
.reset-filter-btn {
|
|
|
|
|
height: 64rpx;
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
border: 1rpx solid #d9dde5;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
.keyword-box {
|
|
|
|
|
padding: 0 16rpx;
|
|
|
|
|
}
|
|
|
|
|
.keyword-input {
|
|
|
|
|
width: 100%;
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #374151;
|
|
|
|
|
}
|
|
|
|
|
.status-box {
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
padding: 0 14rpx;
|
|
|
|
|
}
|
|
|
|
|
.status-box-text {
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #374151;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
.reset-filter-btn {
|
|
|
|
|
justify-content: center;
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #4b5563;
|
|
|
|
|
}
|
|
|
|
|
.list-scroll { height: calc(100vh - 194rpx); }
|
|
|
|
|
.list-wrap { padding: 0 24rpx 32rpx; }
|
|
|
|
|
.task-card { position: relative; margin-top: 20rpx; padding: 28rpx; background: #fff; border-radius: 22rpx; box-shadow: 0 8rpx 28rpx rgba(15, 23, 42, 0.06); }
|
|
|
|
|
.card-header { margin-bottom: 18rpx; }
|
|
|
|
|
|