Files
shj-app/scanpages/hj/daily_audit.vue
T
2026-08-10 15:51:44 +08:00

452 lines
11 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="page-list">
<!-- 头部过滤区域 -->
<view class="filter-header">
<!-- 第一行:管线编号搜索 -->
<view class="search-row">
<u-search v-model="pipelineCode" placeholder="请输入管线编号" :show-action="false" shape="square"
bg-color="#f5f6f8" @change="handleSearch" />
</view>
<!-- 第二行:焊工编号 + 焊接日期 + 单位工程 -->
<view class="filter-row">
<view class="welder-input-wrap">
<input class="welder-input" v-model="welderCode" placeholder="焊工编号" confirm-type="search"
@confirm="handleSearch" @blur="handleSearch" />
</view>
<picker mode="date" :value="weldingDate" @change="onDateChange">
<view class="filter-btn">
<text class="filter-btn__text" :class="{ 'filter-btn__text--placeholder': !weldingDate }">
{{ weldingDate || '焊接日期' }}
</text>
<u-icon v-if="weldingDate" name="close" :size="20" color="#999" @click.stop="onDateClear" />
<u-icon v-else name="calendar" :size="24" color="#999" />
</view>
</picker>
<view class="filter-btn" @click="handleShowUnitWorkSelect">
<text class="filter-btn__text" :class="{ 'filter-btn__text--placeholder': !selectedUnitWork }">
{{ selectedUnitWork?.BaseInfoName || '单位工程' }}
</text>
<u-icon name="arrow-down" :size="18" color="#999" />
</view>
</view>
</view>
<!-- 列表内容 -->
<scroll-view class="list-scroll" scroll-y refresher-enabled="true" :refresher-triggered="refreshing"
@refresherrefresh="handleRefresh">
<view class="list-wrap">
<view v-for="(item, index) in listData" :key="item.TempDetailId || index" class="card-item audit-card"
@click="handleItemClick(item)">
<!-- 勾选框 -->
<view class="check-circle" :class="{ 'check-circle--checked': isSelected(item) }"
@click.stop="toggleSelect(item)">
<u-icon v-if="isSelected(item)" name="checkmark" :size="24" color="#fff" />
</view>
<view class="audit-card__content">
<view class="card-header">
<text class="card-code">{{ item.WeldJointCode || '--' }}</text>
<text class="card-tag status-1">待审核</text>
</view>
<view class="card-body">
<view class="card-row">
<text class="row-label">管线编号</text>
<text class="row-value">{{ item.PipelineCode || '--' }}</text>
</view>
<view class="card-row">
<text class="row-label">焊接日期</text>
<text class="row-value">{{ fmtDate(item.WeldingDate) }}</text>
</view>
<view class="card-row">
<text class="row-label">焊工</text>
<text class="row-value">{{ formatWelders(item) }}</text>
</view>
<view class="card-row">
<text class="row-label">焊接方法</text>
<text class="row-value">{{ item.WeldingMethodCode || '--' }}</text>
</view>
<view class="card-row">
<text class="row-label">提交人</text>
<text class="row-value">{{ item.SubmitPersonName || '--' }}</text>
</view>
<view class="card-row">
<text class="row-label">提交时间</text>
<text class="row-value">{{ fmtDateTime(item.SubmitDate) }}</text>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<u-empty v-if="!loading && listData.length === 0" mode="list" text="暂无待审核日报"></u-empty>
</view>
</scroll-view>
<!-- 底部批量操作栏 -->
<view class="audit-bar">
<view class="audit-bar__all" @click="handleToggleAll">
<view class="check-circle" :class="{ 'check-circle--checked': isAllSelected }">
<u-icon v-if="isAllSelected" name="checkmark" :size="24" color="#fff" />
</view>
<text class="audit-bar__all-text">全选</text>
</view>
<text class="audit-bar__count">已选 {{ selectedIds.length }} 项</text>
<view class="audit-bar__btns">
<u-button size="medium" type="error" :disabled="selectedIds.length === 0"
@click="handleBatchDelete">删除</u-button>
<u-button size="medium" type="primary" :disabled="selectedIds.length === 0"
@click="handleBatchAudit">审核通过</u-button>
</view>
</view>
<!-- 单位工程选择弹窗 -->
<nbd-select v-model="showUnitWorkSelect" :show-search="true" title="请选择单位工程" :list="unitWorkList"
label-key="BaseInfoName" value-key="BaseInfoId" v-model:model="selectedUnitWork"
@confirm="handleUnitWorkConfirm" />
</view>
</template>
<script setup>
import {
ref,
computed
} from 'vue'
import {
onShow
} from '@dcloudio/uni-app'
import {
storeToRefs
} from 'pinia'
import {
useUserStore
} from '@/store'
import {
reqProjectWorkArea
} from '@/api/base.js'
import {
reqPendingWeldingDailyList,
reqAuditWeldingDaily,
reqDeleteWeldingDaily
} from '@/api/hj.js'
const userStore = useUserStore()
const {
currentProject,
userInfo
} = storeToRefs(userStore)
// ===== 筛选条件 =====
const pipelineCode = ref('')
const welderCode = ref('')
const weldingDate = ref('')
const onDateChange = (e) => {
weldingDate.value = e.detail.value
fetchData()
}
const onDateClear = () => {
weldingDate.value = ''
fetchData()
}
// ===== 单位工程选择 =====
const showUnitWorkSelect = ref(false)
const selectedUnitWork = ref(null)
const unitWorkList = ref([])
const handleShowUnitWorkSelect = () => {
reqProjectWorkArea(currentProject.value.ProjectId).then(res => {
unitWorkList.value = [{
BaseInfoId: '',
BaseInfoName: '全部'
}, ...(res.data || [])]
showUnitWorkSelect.value = true
})
}
const handleUnitWorkConfirm = (item) => {
selectedUnitWork.value = item?.BaseInfoId ? item : null
showUnitWorkSelect.value = false
fetchData()
}
// ===== 列表数据 =====
const listData = ref([])
const loading = ref(false)
const refreshing = ref(false)
// 加载待审核列表(不分页,一次拉全部待审核记录)
const fetchData = async () => {
if (loading.value) return
loading.value = true
refreshing.value = true
try {
const res = await reqPendingWeldingDailyList({
projectId: currentProject.value?.ProjectId,
unitWorkId: selectedUnitWork.value?.BaseInfoId || '',
weldingDate: weldingDate.value || '',
pipelineCode: pipelineCode.value || '',
welderCode: welderCode.value || ''
})
listData.value = res.data?.list || res.data?.getDataList || (Array.isArray(res.data) ? res.data : [])
// 刷新后清空已选(原记录可能已不存在)
selectedIds.value = []
} catch (error) {
console.error('加载待审核日报失败:', error)
} finally {
loading.value = false
refreshing.value = false
}
}
const handleRefresh = () => {
fetchData()
}
const handleSearch = () => {
fetchData()
}
// ===== 勾选 =====
const selectedIds = ref([])
const isSelected = (item) => selectedIds.value.includes(item.TempDetailId)
const toggleSelect = (item) => {
const id = item.TempDetailId
const idx = selectedIds.value.indexOf(id)
if (idx > -1) {
selectedIds.value.splice(idx, 1)
} else {
selectedIds.value.push(id)
}
}
const isAllSelected = computed(() =>
listData.value.length > 0 && selectedIds.value.length === listData.value.length
)
const handleToggleAll = () => {
if (isAllSelected.value) {
selectedIds.value = []
} else {
selectedIds.value = listData.value.map(item => item.TempDetailId)
}
}
// ===== 批量操作 =====
const handleBatchAudit = () => {
uni.showModal({
title: '信息提示',
content: `确定审核通过选中的 ${selectedIds.value.length} 条日报吗?`,
success: async ({
confirm
}) => {
if (!confirm) return
try {
await reqAuditWeldingDaily({
TempDetailIds: selectedIds.value,
AuditMan: userInfo.value?.PersonId
})
} catch (err) {
return // 报错已由 request.js 统一 toast
}
uni.showToast({
title: '审核成功',
icon: 'none'
})
fetchData()
}
})
}
const handleBatchDelete = () => {
uni.showModal({
title: '信息提示',
content: `确定删除选中的 ${selectedIds.value.length} 条日报吗?`,
success: async ({
confirm
}) => {
if (!confirm) return
try {
await reqDeleteWeldingDaily({
TempDetailIds: selectedIds.value
})
} catch (err) {
return // 报错已由 request.js 统一 toast
}
uni.showToast({
title: '删除成功',
icon: 'none'
})
fetchData()
}
})
}
// ===== 跳转详情 =====
const handleItemClick = (item) => {
uni.navigateTo({
url: `/scanpages/hj/daily_audit_detail?id=${item.TempDetailId}`
})
}
// ===== 工具 =====
const fmtDate = (val) => {
if (!val) return '--'
return String(val).slice(0, 10)
}
const fmtDateTime = (val) => {
if (!val) return '--'
return String(val).slice(0, 16).replace('T', ' ')
}
// 焊工展示:盖面/打底
const formatWelders = (item) => {
const cover = item.CoverWelderCode || ''
const backing = item.BackingWelderCode || ''
if (cover && backing && cover !== backing) return `${cover}/${backing}`
return cover || backing || '--'
}
// ===== 生命周期 =====
onShow(() => {
fetchData()
})
</script>
<style lang="scss" scoped>
$primary: $app-primary;
.filter-row {
display: flex;
align-items: center;
gap: 12rpx;
.welder-input-wrap {
flex: 1;
min-width: 0;
background: #f5f6f8;
border-radius: 12rpx;
height: 70rpx;
display: flex;
align-items: center;
padding: 0 16rpx;
}
.welder-input {
width: 100%;
font-size: 28rpx;
color: #333;
}
.filter-btn {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
justify-content: space-between;
background: #f5f6f8;
border-radius: 12rpx;
padding: 0 16rpx;
height: 70rpx;
&__text {
font-size: 26rpx;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&--placeholder {
color: #999;
}
}
}
}
// 勾选圆圈
.check-circle {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
border: 2rpx solid #ccc;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
background: #fff;
&--checked {
background: $primary;
border-color: $primary;
}
}
// 带勾选框的卡片
.audit-card {
display: flex;
align-items: flex-start;
gap: 20rpx;
.check-circle {
margin-top: 8rpx;
}
&__content {
flex: 1;
min-width: 0;
}
}
// 底部批量操作栏
.audit-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
padding: 20rpx 32rpx;
display: flex;
align-items: center;
gap: 20rpx;
box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
&__all {
display: flex;
align-items: center;
gap: 10rpx;
}
&__all-text {
font-size: 28rpx;
color: #333;
}
&__count {
flex: 1;
font-size: 26rpx;
color: #999;
}
&__btns {
display: flex;
gap: 16rpx;
.u-size-medium {
height: 72rpx;
font-size: 28rpx;
border-radius: 8rpx;
margin: 0;
padding: 0 32rpx;
}
}
}
// 给底部操作栏留出空间
.list-scroll {
padding-bottom: 140rpx;
}
</style>