Преглед изворни кода

调整记录校核列表和查询数据处理

yangguanjin пре 1 дан
родитељ
комит
3e01034357

+ 8 - 0
src/pages.json

@@ -389,6 +389,10 @@
         "navigationStyle": "custom"
       }
     },
+    {
+      "path": "pages/pendingVerification/list/BoilerItem",
+      "type": "page"
+    },
     {
       "path": "pages/pendingVerification/list/Item",
       "type": "page"
@@ -406,6 +410,10 @@
         }
       }
     },
+    {
+      "path": "pages/pendingVerification/list/PipeItem",
+      "type": "page"
+    },
     {
       "path": "pages/pendingVerification/preViewReport/index",
       "type": "page",

+ 5 - 10
src/pages/equipment/detail/components/checkProjectPopup/BoilerCheckProject.vue

@@ -68,6 +68,7 @@
 <script lang="ts" setup>
 import { ref, computed, onMounted, watch } from 'vue'
 import { getInspectProjectItemPage, addInspectProject } from '@/api/boiler/boilerTaskOrder'
+import { BoilerPressureCheckTypeMap } from '@/utils/dictMap'
 
 interface ReportTemplate {
   orderId: string
@@ -110,15 +111,9 @@ const hadTemplateId = ref('')
 const expandedNames = ref<string[]>(['100'])
 const localSelectedTemplates = ref<ReportTemplate[]>([])
 
-const boilerCheckTypeMap = {
-  100: '内部检验',
-  200: '外部检验',
-  300: '耐压检验',
-}
-
 const boilerCheckTypeLabelName = computed(() => {
   const checkTypeNum = props.equipData?.taskOrder?.checkType
-  return boilerCheckTypeMap[checkTypeNum]
+  return BoilerPressureCheckTypeMap[checkTypeNum]
 })
 
 interface GroupItem {
@@ -142,8 +137,6 @@ const groupedData = computed(() => {
     items: [...dataSource.value],
   })
 
-  console.log(result, dataSource.value)
-
   return result
 })
 
@@ -283,7 +276,7 @@ const handleCancel = () => {
 .dropdown-selector {
   display: flex;
   align-items: center;
-  min-width: 100px;
+  margin: 0 12px;
   padding: 8px 12px;
   background-color: #f5f5f5;
   border-radius: 4px;
@@ -331,6 +324,8 @@ const handleCancel = () => {
 .search-input {
   flex: 1;
   padding: 0 12px;
+  height: 100%;
+  margin: 0 12px 0 0;
   font-size: 14px;
   background-color: #f5f5f5;
   border-radius: 4px;

+ 6 - 13
src/pages/equipment/detail/components/checkProjectPopup/PipeCheckProject.vue

@@ -67,6 +67,7 @@
 <script lang="ts" setup>
 import { ref, computed, onMounted, watch } from 'vue'
 import { getInspectProjectItemPage, addInspectProject } from '@/api/pipe/pipeTaskOrder'
+import { PipeCheckTypeMap } from '@/utils/dictMap'
 
 interface ReportTemplate {
   orderId: string
@@ -110,19 +111,9 @@ const hadTemplateId = ref('')
 const expandedNames = ref<string[]>(['100'])
 const localSelectedTemplates = ref<ReportTemplate[]>([])
 
-const inspectionNatureOptions = [
-  { label: '定期检验', value: 100 },
-  { label: '监督检验', value: 200 },
-]
-
-const pipeInspectionNatureMap = {
-  100: '定期检验',
-  200: '年度检查',
-}
-
 const inspectionNatureLabel = computed(() => {
   const checkTypeNum = props.equipData?.taskOrder?.checkType
-  return pipeInspectionNatureMap[checkTypeNum]
+  return PipeCheckTypeMap[checkTypeNum]
 })
 
 interface GroupItem {
@@ -290,7 +281,7 @@ const handleCancel = () => {
 .dropdown-selector {
   display: flex;
   align-items: center;
-  min-width: 100px;
+  margin: 0 12px;
   padding: 8px 12px;
   background-color: #f5f5f5;
   border-radius: 4px;
@@ -337,7 +328,9 @@ const handleCancel = () => {
 
 .search-input {
   flex: 1;
-  padding: 8px 12px;
+  padding: 0 12px;
+  height: 100%;
+  margin: 0 12px 0 0;
   font-size: 14px;
   background-color: #f5f5f5;
   border-radius: 4px;

+ 17 - 3
src/pages/inspectionPlanAudit/components/Item.vue

@@ -6,9 +6,6 @@
           <view>
             <text class="item-top-text">任务单号:{{ item.orderNo }}</text>
           </view>
-          <button v-show="item.status == '100'" class="main-btn" @click="handleOperation">
-            <text class="main-btn-text">{{ operateText }}</text>
-          </button>
         </view>
       </view>
     </view>
@@ -60,6 +57,14 @@
         </view>
       </view>
     </view>
+
+
+    <view class="btn-group">
+      <button v-show="item.status == '100'" class="main-btn" @click="handleOperation">
+          <text class="main-btn-text">{{ operateText }}</text>
+      </button>
+    </view>
+
   </view>
 </template>
 
@@ -153,6 +158,7 @@ const handleOperation = () => {
   display: flex;
   justify-content: center;
   align-items: center;
+  margin: 0;
   background-color: rgb(47, 142, 255);
   border: none;
   padding: 0;
@@ -206,4 +212,12 @@ const handleOperation = () => {
   color: rgb(251, 127, 55);
   font-size: 12px;
 }
+
+.btn-group {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-end;
+  margin-top: 10px;
+}
 </style>

+ 276 - 0
src/pages/pendingVerification/components/query/BoilerQueryView.vue

@@ -0,0 +1,276 @@
+<template>
+  <view class="query-view">
+    <view class="query-content" :style="contentStyle">
+      <view class="query-left">
+        <InputCom
+          ref="orderNoRef"
+          title="任务单号:"
+          type="orderNo"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('orderNo', $event)"
+        />
+        <CheckNatureCom
+          ref="checkTypeRef"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('checkType', $event)"
+        />
+        <CheckDateCom
+          ref="checkDateRef"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('checkDate', $event)"
+        />
+        <!-- <CellCom
+          ref="mainCheckerStrIdsRef"
+          title="主检人:"
+          type="mainCheckerStrIds"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0, marginBottom: 0 }"
+          @click="showUserListPopup('主检人', 'mainCheckerStrIds')"
+        />
+        <CellCom
+          ref="managerIdRef"
+          title="项目负责人:"
+          type="managerId"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0, marginBottom: 0 }"
+          @click="showUserListPopup('项目负责人', 'managerId')"
+        /> -->
+      </view>
+
+      <view class="query-right">
+        <CellCom
+          ref="queryTypeRef"
+          :title="queryType.value + ':'"
+          :type="queryType.id"
+          :text-style="{ width: '90px' }"
+          :style="{ marginLeft: 0 }"
+          :default-value="defaultValue"
+          @click="showUserListPopup(queryType.value, queryType.id)"
+        />
+        <InputCom
+          ref="equipCodeRef"
+          title="设备注册代码:"
+          type="equipCode"
+          :text-style="{ width: '90px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('equipCode', $event)"
+        />
+        <InputCom
+          ref="unitNameRef"
+          title="单位名称:"
+          type="unitName"
+          :text-style="{ width: '90px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('unitName', $event)"
+        />
+        <!-- <CellCom
+          ref="checkUserStrIdsRef"
+          title="检验员:"
+          type="checkUserStrIds"
+          :text-style="{ width: '90px' }"
+          :style="{ marginLeft: 0, marginBottom: 0 }"
+          @click="showUserListPopup('检验员', 'checkUserStrIds')"
+        /> -->
+
+        <view class="btn-group">
+          <button class="btn reset-btn" @click="reset">重置</button>
+          <button class="btn query-btn" @click="query">查询</button>
+        </view>
+      </view>
+    </view>
+
+    <view class="query-toggle" @click="toggleFilter">
+      <text class="query-toggle-text">查询</text>
+      <image
+        class="arrow-icon"
+        :src="iconMap.ArrowDown"
+        :class="{ 'arrow-rotate': isOpen }"
+      />
+    </view>
+  </view>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, computed } from 'vue'
+import { useUserStore } from '@/store/user'
+import iconMap from '@/utils/imagesMap'
+import InputCom from './InputCom.vue'
+import CheckDateCom from './CheckDateCom.vue'
+import CheckNatureCom from './CheckNatureCom.vue'
+import CellCom from './CellCom.vue'
+
+interface Props {
+  queryType: { value: string; id: string }
+}
+
+const props = defineProps<Props>()
+
+const emit = defineEmits<{
+  queryAction: [params: Record<string, any>]
+}>()
+
+const userStore = useUserStore()
+const userInfo = computed(() => userStore.userInfo)
+
+const isOpen = ref(false)
+const params = reactive<Record<string, any>>({
+  orderNo: '',
+  checkType: '',
+  mainCheckerStrIds: '',
+  [props.queryType.id]: userInfo.value?.id || '',
+  checkDate: '',
+  checkUserStrIds: '',
+  equipCode: '',
+  unitName: '',
+  managerId: '',
+})
+
+const defaultValue = computed(() => userInfo.value?.nickname || '')
+
+const contentStyle = computed(() => ({
+  height: isOpen.value ? '220px' : '0',
+  opacity: isOpen.value ? 1 : 0,
+  overflow: 'hidden',
+  transition: 'all 0.3s',
+}))
+
+const orderNoRef = ref<any>(null)
+const checkTypeRef = ref<any>(null)
+const checkDateRef = ref<any>(null)
+const mainCheckerStrIdsRef = ref<any>(null)
+const managerIdRef = ref<any>(null)
+const queryTypeRef = ref<any>(null)
+const equipCodeRef = ref<any>(null)
+const unitNameRef = ref<any>(null)
+const checkUserStrIdsRef = ref<any>(null)
+
+const toggleFilter = () => {
+  isOpen.value = !isOpen.value
+}
+
+const handleChange = (propName: string, value: any) => {
+  params[propName] = value
+}
+
+const reset = () => {
+  orderNoRef.value?.reset()
+  checkTypeRef.value?.reset()
+  checkDateRef.value?.reset()
+  mainCheckerStrIdsRef.value?.reset()
+  managerIdRef.value?.reset()
+  equipCodeRef.value?.reset()
+  unitNameRef.value?.reset()
+  checkUserStrIdsRef.value?.reset()
+
+  Object.assign(params, {
+    orderNo: '',
+    checkType: '',
+    mainCheckerStrIds: '',
+    [props.queryType.id]: userInfo.value?.id || '',
+    checkDate: '',
+    checkUserStrIds: '',
+    equipCode: '',
+    unitName: '',
+    managerId: '',
+  })
+
+  emit('queryAction', params)
+}
+
+const query = () => {
+  Object.assign(params, {
+    checkType: checkTypeRef.value?.inputContent,
+    checkDate: checkDateRef.value?.inputContent,
+  })
+  emit('queryAction', params)
+}
+
+const showUserListPopup = (title: string, type: string) => {
+  console.log('显示用户列表弹窗:', title, type)
+}
+</script>
+
+<style lang="scss" scoped>
+.query-view {
+  width: 100%;
+  background-color: #fff;
+}
+
+.query-content {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  justify-content: space-between;
+  padding: 0 15px;
+}
+
+.query-left,
+.query-right {
+  flex: 1;
+  padding: 15px 0;
+}
+
+.query-right {
+  margin-left: 10px;
+}
+
+.btn-group {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  margin-top: 10px;
+  padding: 0 10%;
+  gap: 10%;
+}
+
+.btn {
+  padding: 0 15px;
+  height: 30px;
+  margin-left: 5px;
+  border-radius: 3px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 15px;
+  border: none;
+}
+
+.reset-btn {
+  background-color: #fff;
+  color: rgb(47, 142, 255);
+  border: 1px solid rgb(47, 142, 255);
+}
+
+.query-btn {
+  background-color: rgb(47, 142, 255);
+  color: rgb(222, 238, 255);
+}
+
+.query-toggle {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0 20px;
+  height: 60px;
+  border-top: 1px solid rgba(187, 187, 187, 0.8);
+}
+
+.query-toggle-text {
+  color: rgb(51, 51, 51);
+  font-size: 16px;
+}
+
+.arrow-icon {
+  width: 21px;
+  height: 21px;
+  transition: transform 0.3s;
+}
+
+.arrow-rotate {
+  transform: rotate(180deg);
+}
+</style>

+ 63 - 46
src/pages/pendingVerification/components/query/CheckDateCom.vue

@@ -1,16 +1,26 @@
 <template>
   <view class="check-date-box" :style="style">
-    <text class="title" :style="textStyle">检验时间:</text>
-    <view class="date-input" @click="handleClick">
-      <text class="date-text">
-        {{ displayText || '请选择日期范围' }}
-      </text>
-    </view>
+    <view class="title" :style="textStyle">检验时间:</view>
+    <wd-datetime-picker
+      class="date-picker"
+      v-model="dateRange"
+      type="date"
+      :min-date="minDate"
+      :max-date="maxDate"
+      :default-value="defaultValue"
+      @confirm="onConfirm"
+    >
+      <view class="date-input">
+        <text :class="['date-text', { 'date-text--placeholder': !displayText }]">
+          {{ displayText || '请选择日期范围' }}
+        </text>
+      </view>
+    </wd-datetime-picker>
   </view>
 </template>
 
 <script lang="ts" setup>
-import { ref } from 'vue'
+import { ref, computed } from 'vue'
 import dayjs from 'dayjs'
 
 interface Props {
@@ -24,43 +34,37 @@ const emit = defineEmits<{
   change: [date: string[], type: string]
 }>()
 
-const rangeStartDate = ref(dayjs().format('YYYY-MM-DD HH:mm:ss'))
-const rangeEndDate = ref(dayjs().format('YYYY-MM-DD HH:mm:ss'))
-const displayText = ref('')
+const minDate = new Date(new Date().getFullYear() - 10, 0, 1).getTime()
+const maxDate = new Date(new Date().getFullYear() + 10, 11, 31).getTime()
+const defaultValue = [Date.now(), Date.now()]
 
-// 暴露方法
-defineExpose({
-  reset: () => {
-    rangeStartDate.value = dayjs().format('YYYY-MM-DD HH:mm:ss')
-    rangeEndDate.value = dayjs().format('YYYY-MM-DD HH:mm:ss')
-    displayText.value = ''
-  },
-  inputContent: displayText.value ? [rangeStartDate.value, rangeEndDate.value] : '',
-})
-
-// 点击选择日期
-const handleClick = () => {
-  const startDatePart = rangeStartDate.value.split(' ')[0]
-  const endDatePart = rangeEndDate.value.split(' ')[0]
-
-  uni.navigateTo({
-    url: `/pages/dateRangePicker/index?startDate=${startDatePart}&endDate=${endDatePart}&type=checkDate`,
-  })
-}
-
-// 监听日期选择事件
-uni.$on('DateRangeSelected', (data: any) => {
-  if (data.type === 'checkDate') {
-    const startDateTime = `${data.startDate} 00:00:00`
-    const endDateTime = `${data.endDate} 23:59:59`
+const dateRange = ref<(number | string)[]>([])
 
-    rangeStartDate.value = startDateTime
-    rangeEndDate.value = endDateTime
-
-    displayText.value = `${dayjs(data.startDate).format('YYYY-MM-DD')} 至 ${dayjs(data.endDate).format('YYYY-MM-DD')}`
+const displayText = computed(() => {
+  if (!dateRange.value || dateRange.value.length < 2 || !dateRange.value[0] || !dateRange.value[1]) {
+    return ''
+  }
+  const start = dayjs(Number(dateRange.value[0])).format('YYYY-MM-DD')
+  const end = dayjs(Number(dateRange.value[1])).format('YYYY-MM-DD')
+  return `${start} 至 ${end}`
+})
 
+const onConfirm = ({ value }: { value: (number | string)[] }) => {
+  if (value && value.length === 2) {
+    const startDateTime = `${dayjs(Number(value[0])).format('YYYY-MM-DD')} 00:00:00`
+    const endDateTime = `${dayjs(Number(value[1])).format('YYYY-MM-DD')} 23:59:59`
     emit('change', [startDateTime, endDateTime], 'checkDate')
   }
+}
+
+defineExpose({
+  reset: () => {
+    dateRange.value = []
+  },
+  inputContent: computed(() => {
+    if (!dateRange.value || dateRange.value.length < 2) return ''
+    return [dateRange.value[0], dateRange.value[1]]
+  }),
 })
 </script>
 
@@ -69,28 +73,41 @@ uni.$on('DateRangeSelected', (data: any) => {
   display: flex;
   flex-direction: row;
   align-items: center;
-  margin-bottom: 10px;
+  margin-bottom: 10px !important;
 }
 
 .title {
-  color: rgb(51, 51, 51);
+  flex-shrink: 0;
+  width: 60px;
   font-size: 12px;
-  width: 70px;
+  color: rgb(51, 51, 51);
   text-align: right;
 }
 
+.date-picker {
+  flex: 1;
+  min-width: 0;
+}
+
 .date-input {
+  box-sizing: border-box;
+  display: flex;
   flex: 1;
+  align-items: center;
+  min-width: 0;
   height: 30px;
+  min-height: 30px;
+  padding: 0 5px;
   border: 1px solid #ccc;
   border-radius: 6px;
-  padding: 0 5px;
-  display: flex;
-  align-items: center;
 }
 
 .date-text {
-  color: rgba(136, 136, 136, 1);
   font-size: 12px;
+  color: rgb(51, 51, 51);
+
+  &--placeholder {
+    color: rgba(136, 136, 136, 1);
+  }
 }
 </style>

+ 79 - 51
src/pages/pendingVerification/components/query/CheckNatureCom.vue

@@ -1,25 +1,37 @@
 <template>
-  <view class="check-nature-box" :style="style">
-    <text class="title" :style="textStyle">检验性质:</text>
-    <view class="nature-input" @click="showPicker">
-      <text class="nature-text">{{ selectorChecked || '请选择' }}</text>
-      <image
-        class="arrow-icon"
-        :src="iconMap.ArrowDown"
-        :class="{ 'arrow-rotate': isOpen }"
-      />
-    </view>
+  <view class="check-nature-box">
+    <view class="title" :style="textStyle">检验性质:</view>
+    <wd-picker
+      class="nature-picker"
+      v-model="selectCode"
+      :columns="columns"
+      @confirm="onConfirm"
+    >
+      <view class="nature-input">
+        <text :class="['nature-text', { 'nature-text--placeholder': !displayLabel }]">
+          {{ displayLabel || '请选择' }}
+        </text>
+      </view>
+    </wd-picker>
   </view>
 </template>
 
 <script lang="ts" setup>
-import { ref } from 'vue'
-import iconMap from '@/utils/imagesMap'
-import { getCheckTypeFromText } from '@/utils/dictMap'
+import { ref, computed } from 'vue'
+import {
+  EquipmentType,
+  BoilerPressureCheckTypeMap,
+  PipeCheckTypeMap,
+  PressureCheckTypeMap,
+} from '@/utils/dictMap'
+import { useConfigStore } from '@/store/config'
+
+const configStore = useConfigStore()
+const equipType = configStore.getEquipType()
 
 interface Props {
+  type: string
   textStyle?: any
-  style?: any
 }
 
 const props = defineProps<Props>()
@@ -28,36 +40,50 @@ const emit = defineEmits<{
   change: [text: number, type: string]
 }>()
 
-const isOpen = ref(false)
-const selectorChecked = ref('')
 const selectCode = ref<number | undefined>(undefined)
 
-const itemList = ['定期检验', '年度检查', '超年限检验']
+const columns = computed(() => {
+  let checkTypeMap = PressureCheckTypeMap
+  switch(equipType) {
+    case EquipmentType.BOILER:
+      checkTypeMap = BoilerPressureCheckTypeMap
+      break
+    case EquipmentType.PIPE:
+      checkTypeMap = PipeCheckTypeMap
+      break
+    default:
+      checkTypeMap = PressureCheckTypeMap
+  }
+
+  const columns = []
+  for (const key in checkTypeMap) {
+    columns.push({
+      label: checkTypeMap[key],
+      value: key,
+    })
+  }
+
+  return columns
+})
+
+const displayLabel = computed(() => {
+  if (selectCode.value == null) return ''
+  const item = columns.value.find((c: any) => c.value === selectCode.value)
+  return item ? item.label : ''
+})
+
+const onConfirm = ({ value }: { value: number }) => {
+  if (value) {
+    emit('change', value, props.type)
+  }
+}
 
-// 暴露方法
 defineExpose({
   reset: () => {
-    selectorChecked.value = ''
     selectCode.value = undefined
   },
-  inputContent: selectCode.value || undefined,
+  inputContent: computed(() => selectCode.value || undefined),
 })
-
-// 显示选择器
-const showPicker = () => {
-  uni.showActionSheet({
-    itemList,
-    success: (res) => {
-      const selected = itemList[res.tapIndex]
-      selectorChecked.value = selected
-      const code = getCheckTypeFromText(selected)
-      if (code) {
-        selectCode.value = code
-        emit('change', code, 'checkType')
-      }
-    },
-  })
-}
 </script>
 
 <style lang="scss" scoped>
@@ -69,36 +95,38 @@ const showPicker = () => {
 }
 
 .title {
-  color: rgb(51, 51, 51);
+  flex-shrink: 0;
+  width: 60px;
   font-size: 12px;
-  width: 70px;
+  color: rgb(51, 51, 51);
   text-align: right;
 }
 
-.nature-input {
+.nature-picker {
   flex: 1;
+  min-width: 0;
+}
+
+.nature-input {
+  box-sizing: border-box;
   display: flex;
+  flex: 1;
   flex-direction: row;
   align-items: center;
-  justify-content: space-between;
+  min-width: 0;
   height: 30px;
+  min-height: 30px;
+  padding: 0 5px;
   border: 1px solid #ccc;
   border-radius: 6px;
-  padding: 0 5px;
 }
 
 .nature-text {
-  color: rgba(136, 136, 136, 1);
   font-size: 12px;
-}
-
-.arrow-icon {
-  width: 15px;
-  height: 15px;
-  transition: transform 0.3s;
-}
+  color: rgb(51, 51, 51);
 
-.arrow-rotate {
-  transform: rotate(180deg);
+  &--placeholder {
+    color: rgba(136, 136, 136, 1);
+  }
 }
 </style>

+ 276 - 0
src/pages/pendingVerification/components/query/PipeQueryView.vue

@@ -0,0 +1,276 @@
+<template>
+  <view class="query-view">
+    <view class="query-content" :style="contentStyle">
+      <view class="query-left">
+        <InputCom
+          ref="orderNoRef"
+          title="任务单号:"
+          type="orderNo"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('orderNo', $event)"
+        />
+        <CheckNatureCom
+          ref="checkTypeRef"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('checkType', $event)"
+        />
+        <CheckDateCom
+          ref="checkDateRef"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('checkDate', $event)"
+        />
+        <!-- <CellCom
+          ref="mainCheckerStrIdsRef"
+          title="主检人:"
+          type="mainCheckerStrIds"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0, marginBottom: 0 }"
+          @click="showUserListPopup('主检人', 'mainCheckerStrIds')"
+        />
+        <CellCom
+          ref="managerIdRef"
+          title="项目负责人:"
+          type="managerId"
+          :text-style="{ width: '80px' }"
+          :style="{ marginLeft: 0, marginBottom: 0 }"
+          @click="showUserListPopup('项目负责人', 'managerId')"
+        /> -->
+      </view>
+
+      <view class="query-right">
+        <CellCom
+          ref="queryTypeRef"
+          :title="queryType.value + ':'"
+          :type="queryType.id"
+          :text-style="{ width: '90px' }"
+          :style="{ marginLeft: 0 }"
+          :default-value="defaultValue"
+          @click="showUserListPopup(queryType.value, queryType.id)"
+        />
+        <InputCom
+          ref="projectNoRef"
+          title="工程号:"
+          type="projectNo"
+          :text-style="{ width: '90px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('projectNo', $event)"
+        />
+        <InputCom
+          ref="unitNameRef"
+          title="单位名称:"
+          type="unitName"
+          :text-style="{ width: '90px' }"
+          :style="{ marginLeft: 0 }"
+          @change="handleChange('unitName', $event)"
+        />
+        <!-- <CellCom
+          ref="checkUserStrIdsRef"
+          title="检验员:"
+          type="checkUserStrIds"
+          :text-style="{ width: '90px' }"
+          :style="{ marginLeft: 0, marginBottom: 0 }"
+          @click="showUserListPopup('检验员', 'checkUserStrIds')"
+        /> -->
+
+        <view class="btn-group">
+          <button class="btn reset-btn" @click="reset">重置</button>
+          <button class="btn query-btn" @click="query">查询</button>
+        </view>
+      </view>
+    </view>
+
+    <view class="query-toggle" @click="toggleFilter">
+      <text class="query-toggle-text">查询</text>
+      <image
+        class="arrow-icon"
+        :src="iconMap.ArrowDown"
+        :class="{ 'arrow-rotate': isOpen }"
+      />
+    </view>
+  </view>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, computed } from 'vue'
+import { useUserStore } from '@/store/user'
+import iconMap from '@/utils/imagesMap'
+import InputCom from './InputCom.vue'
+import CheckDateCom from './CheckDateCom.vue'
+import CheckNatureCom from './CheckNatureCom.vue'
+import CellCom from './CellCom.vue'
+
+interface Props {
+  queryType: { value: string; id: string }
+}
+
+const props = defineProps<Props>()
+
+const emit = defineEmits<{
+  queryAction: [params: Record<string, any>]
+}>()
+
+const userStore = useUserStore()
+const userInfo = computed(() => userStore.userInfo)
+
+const isOpen = ref(false)
+const params = reactive<Record<string, any>>({
+  orderNo: '',
+  checkType: '',
+  mainCheckerStrIds: '',
+  [props.queryType.id]: userInfo.value?.id || '',
+  checkDate: '',
+  checkUserStrIds: '',
+  projectNo: '',
+  unitName: '',
+  managerId: '',
+})
+
+const defaultValue = computed(() => userInfo.value?.nickname || '')
+
+const contentStyle = computed(() => ({
+  height: isOpen.value ? '220px' : '0',
+  opacity: isOpen.value ? 1 : 0,
+  overflow: 'hidden',
+  transition: 'all 0.3s',
+}))
+
+const orderNoRef = ref<any>(null)
+const checkTypeRef = ref<any>(null)
+const checkDateRef = ref<any>(null)
+const mainCheckerStrIdsRef = ref<any>(null)
+const managerIdRef = ref<any>(null)
+const queryTypeRef = ref<any>(null)
+const projectNoRef = ref<any>(null)
+const unitNameRef = ref<any>(null)
+const checkUserStrIdsRef = ref<any>(null)
+
+const toggleFilter = () => {
+  isOpen.value = !isOpen.value
+}
+
+const handleChange = (propName: string, value: any) => {
+  params[propName] = value
+}
+
+const reset = () => {
+  orderNoRef.value?.reset()
+  checkTypeRef.value?.reset()
+  checkDateRef.value?.reset()
+  mainCheckerStrIdsRef.value?.reset()
+  managerIdRef.value?.reset()
+  projectNoRef.value?.reset()
+  unitNameRef.value?.reset()
+  checkUserStrIdsRef.value?.reset()
+
+  Object.assign(params, {
+    orderNo: '',
+    checkType: '',
+    mainCheckerStrIds: '',
+    [props.queryType.id]: userInfo.value?.id || '',
+    checkDate: '',
+    checkUserStrIds: '',
+    projectNo: '',
+    unitName: '',
+    managerId: '',
+  })
+
+  emit('queryAction', params)
+}
+
+const query = () => {
+  Object.assign(params, {
+    checkType: checkTypeRef.value?.inputContent,
+    checkDate: checkDateRef.value?.inputContent,
+  })
+  emit('queryAction', params)
+}
+
+const showUserListPopup = (title: string, type: string) => {
+  console.log('显示用户列表弹窗:', title, type)
+}
+</script>
+
+<style lang="scss" scoped>
+.query-view {
+  width: 100%;
+  background-color: #fff;
+}
+
+.query-content {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  padding: 0 15px;
+}
+
+.query-left,
+.query-right {
+  flex: 1;
+  padding: 15px 0;
+}
+
+.query-right {
+  margin-left: 10px;
+}
+
+.btn-group {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  margin-top: 10px;
+  padding: 0 10%;
+  gap: 10%;
+}
+
+.btn {
+  padding: 0 15px;
+  height: 30px;
+  margin-left: 5px;
+  border-radius: 3px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 15px;
+  border: none;
+}
+
+.reset-btn {
+  background-color: #fff;
+  color: rgb(47, 142, 255);
+  border: 1px solid rgb(47, 142, 255);
+}
+
+.query-btn {
+  background-color: rgb(47, 142, 255);
+  color: rgb(222, 238, 255);
+}
+
+.query-toggle {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0 20px;
+  // height: 60px;
+  border-top: 1px solid rgba(187, 187, 187, 0.8);
+}
+
+.query-toggle-text {
+  color: rgb(51, 51, 51);
+  font-size: 16px;
+}
+
+.arrow-icon {
+  width: 21px;
+  height: 21px;
+  transition: transform 0.3s;
+}
+
+.arrow-rotate {
+  transform: rotate(180deg);
+}
+</style>

+ 242 - 0
src/pages/pendingVerification/list/BoilerItem.vue

@@ -0,0 +1,242 @@
+<template>
+  <view class="item-box">
+    <view class="item-top">
+      <view class="item-top-left">
+        <view class="row">
+          <text class="item-top-text">
+            任务单号:{{ item.orderNo }}
+            <text>
+              (
+              <text :style="{ color: checkTypeColor }">{{ checkType }}</text>
+              )
+            </text>
+          </text>
+          <text v-if="item.equipNum" class="item-top-num-box">{{ item.equipNum }}台</text>
+        </view>
+      </view>
+    </view>
+
+    <view class="item-center">
+      <view class="row-center">
+        <text class="title">
+          检测时间:
+          <text class="text">{{ checkDate }}</text>
+        </text>
+        <text class="title">
+          设备注册代码:
+          <text class="text">{{ item.equipCode }}</text>
+        </text>
+        <view class="row">
+          <text class="title">主报告状态:</text>
+          <view class="status-badge">
+            <text class="status-text">{{ taskStatusText }}</text>
+          </view>
+        </view>
+      </view>
+
+      <text class="title">
+        使用单位:
+        <text class="text">{{ item.unitName }}</text>
+      </text>
+      <view class="row-center">
+        <text class="title">
+          项目负责人:
+          <text class="text">{{ item?.manager?.nickname }}</text>
+        </text>
+        <text class="title">
+          主检人:
+          <text class="text">{{ item?.mainCheckerUser?.nickname }}</text>
+        </text>
+      </view>
+      <text class="title">
+        检验员:
+        <text class="text">{{ checkUsersText }}</text>
+      </text>
+      <text class="title">
+        检验项目:
+        <text class="text">{{ reportText }}</text>
+      </text>
+    </view>
+
+    <view class="btn-group">
+      <button class="main-btn" @click="handleOperation">
+          <text class="main-btn-text">{{ operateText }}</text>
+      </button>
+    </view>
+
+  </view>
+</template>
+
+<script lang="ts" setup>
+import { computed } from 'vue'
+import { BoilerPressureCheckTypeMap } from '@/utils/dictMap'
+import { PressureCheckerMyTaskStatusMap } from '@/utils/dictMap'
+
+interface Props {
+  item: any
+  reportDOList: any[]
+  operateText: string
+}
+
+const props = defineProps<Props>()
+
+const emit = defineEmits<{
+  handleOperation: [item: any, reportDOList: any]
+}>()
+
+const checkType = computed(() => {
+  return BoilerPressureCheckTypeMap[props.item.checkType] || ''
+})
+
+const checkTypeColor = computed(() => {
+  switch (props.item.checkType) {
+    case 200:
+      return 'rgb(251,127,55)'
+    case 300:
+      return '#ff4d4f'
+    default:
+      return '#2F8EFF'
+  }
+})
+
+const checkDate = computed(() => {
+  return props.item.checkDate ? props.item.checkDate.join('-') : ''
+})
+
+const checkUsersText = computed(() => {
+  const checkUsers = props.item?.checkUsers?.map((check: any) => check.nickname)
+  return checkUsers?.length > 0 ? checkUsers.join(',') : ''
+})
+
+const reportText = computed(() => {
+  return props.reportDOList?.map((item) => item.reportName)?.join('、') || ''
+})
+
+const taskStatusText = computed(() => {
+  return PressureCheckerMyTaskStatusMap[props.item.taskStatus] || ''
+})
+
+const handleOperation = () => {
+  emit('handleOperation', props.item, props.reportDOList)
+}
+</script>
+
+<style lang="scss" scoped>
+.item-box {
+  margin: 13px;
+  padding: 13px;
+  background-color: #fff;
+  border-radius: 5px;
+}
+
+.row {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+
+.item-top {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  align-items: center;
+  border-bottom: 1px solid rgb(244, 244, 244);
+  padding-bottom: 10px;
+  margin-bottom: 10px;
+}
+
+.item-top-left {
+  flex: 1;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.item-top-text {
+  font-size: 17px;
+  color: rgb(51, 51, 51);
+  font-weight: bold;
+}
+
+.item-top-num-box {
+  border-radius: 2px;
+  background-color: rgb(255, 227, 210);
+  padding: 3px;
+  min-width: 46px;
+  text-align: center;
+  font-size: 12px;
+  color: rgb(251, 127, 55);
+}
+
+.main-btn {
+  width: 82px;
+  height: 29px;
+  border-radius: 3px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: rgb(47, 142, 255);
+  margin: 0;
+  border: none;
+  padding: 0;
+}
+
+.main-btn-text {
+  color: rgb(222, 238, 255);
+  font-size: 15px;
+}
+
+.item-center {
+  display: flex;
+  flex-direction: column;
+  padding: 8px 12px;
+  background-color: rgb(244, 244, 244);
+  border-radius: 5px;
+}
+
+.row-center {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.title {
+  color: rgb(108, 108, 108);
+  font-size: 12px;
+  line-height: 25px;
+  margin-right: 5px;
+}
+
+.text {
+  color: rgb(51, 51, 51);
+  font-size: 12px;
+  line-height: 25px;
+}
+
+.status-badge {
+  height: 25px;
+  padding: 0 5px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #ffe3d2;
+  border-radius: 3px;
+}
+
+.status-text {
+  color: rgb(251, 127, 55);
+  font-size: 12px;
+}
+
+.btn-group {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-end;
+  margin-top: 10px;
+}
+</style>

+ 16 - 3
src/pages/pendingVerification/list/Item.vue

@@ -13,9 +13,6 @@
           </text>
           <text v-if="item.equipNum" class="item-top-num-box">{{ item.equipNum }}台</text>
         </view>
-        <button class="main-btn" @click="handleOperation">
-          <text class="main-btn-text">{{ operateText }}</text>
-        </button>
       </view>
     </view>
 
@@ -60,6 +57,13 @@
         <text class="text">{{ reportText }}</text>
       </text>
     </view>
+
+    <view class="btn-group">
+      <button class="main-btn" @click="handleOperation">
+          <text class="main-btn-text">{{ operateText }}</text>
+      </button>
+    </view>
+
   </view>
 </template>
 
@@ -189,6 +193,7 @@ const handleOperation = () => {
   justify-content: center;
   align-items: center;
   background-color: rgb(47, 142, 255);
+  margin: 0;
   border: none;
   padding: 0;
 }
@@ -241,4 +246,12 @@ const handleOperation = () => {
   color: rgb(251, 127, 55);
   font-size: 12px;
 }
+
+.btn-group {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-end;
+  margin-top: 10px;
+}
 </style>

+ 35 - 9
src/pages/pendingVerification/list/PendingVerificationList.vue

@@ -18,12 +18,17 @@
     <NavBar title="记录校核" />
 
     <!-- 查询视图 -->
-    <QueryView :query-type="queryType" @query-action="queryAction" />
+    <component
+      :is="queryViewComponent"
+      :query-type="queryType"
+      @query-action="queryAction"
+    />
 
     <!-- 列表 -->
     <scroll-view class="list-scroll" scroll-y @scrolltolower="loadMore">
       <view v-for="item in listData" :key="item.reportId" class="item-box">
-        <Item
+        <component
+          :is="taskItemComponent"
           :item="item"
           :reportDOList="reportDOList(item)"
           :operate-text="'校核'"
@@ -41,14 +46,17 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
+import { ref, reactive, computed } from 'vue'
 import { useUserStore } from '@/store/user'
 import { useConfigStore } from '@/store/config'
-import QueryView from '@/pages/pendingVerification/components/query/QueryView.vue'
-import Item from '@/pages/pendingVerification/list/Item.vue'
+import BoilerQueryView from '@/pages/pendingVerification/components/query/BoilerQueryView.vue'
+import PipeQueryView from '@/pages/pendingVerification/components/query/PipeQueryView.vue'
+import BoilerItem from '@/pages/pendingVerification/list/BoilerItem.vue'
+import PipeItem from '@/pages/pendingVerification/list/PipeItem.vue'
 import NavBar from '@/components/NavBar/NavBar.vue'
 import { requestFunc, TaskOrderFuncName } from '@/api/ApiRouter/taskOrder'
 import { onShow } from '@dcloudio/uni-app'
+import { EquipmentType } from '@/utils/dictMap'
 
 defineOptions({
   name: 'PendingVerificationList',
@@ -68,6 +76,28 @@ const userStore = useUserStore()
 const userInfo = computed(() => userStore.userInfo)
 const equipType = useConfigStore().getEquipType()
 
+const taskItemComponent = computed(() => {
+  switch (equipType) {
+    case EquipmentType.BOILER:
+      return BoilerItem
+    case EquipmentType.PIPE:
+      return PipeItem
+    default:
+      return BoilerItem
+  }
+})
+
+const queryViewComponent = computed(() => {
+  switch (equipType) {
+    case EquipmentType.BOILER:
+      return BoilerQueryView
+    case EquipmentType.PIPE:
+      return PipeQueryView
+    default:
+      return BoilerQueryView
+  }
+})
+
 // 初始化参数
 params.recheckStrIds = userInfo.value?.id || ''
 
@@ -162,10 +192,6 @@ onShow(() => {
   refreshList()
   uni.$on('RefreshVerificationListApi', refreshListener)
 })
-
-onUnmounted(() => {
-  uni.$off('RefreshVerificationListApi', refreshListener)
-})
 </script>
 
 <style lang="scss" scoped>

+ 242 - 0
src/pages/pendingVerification/list/PipeItem.vue

@@ -0,0 +1,242 @@
+<template>
+  <view class="item-box">
+    <view class="item-top">
+      <view class="item-top-left">
+        <view class="row">
+          <text class="item-top-text">
+            任务单号:{{ item.orderNo }}
+            <text>
+              (
+              <text :style="{ color: checkTypeColor }">{{ checkType }}</text>
+              )
+            </text>
+          </text>
+          <text v-if="item.equipNum" class="item-top-num-box">{{ item.equipNum }}台</text>
+        </view>
+      </view>
+    </view>
+
+    <view class="item-center">
+      <view class="row-center">
+        <text class="title">
+          检测时间:
+          <text class="text">{{ checkDate }}</text>
+        </text>
+        <text class="title">
+          工程号:
+          <text class="text">{{ item.projectNo || '-' }}</text>
+        </text>
+        <view class="row">
+          <text class="title">主报告状态:</text>
+          <view class="status-badge">
+            <text class="status-text">{{ taskStatusText }}</text>
+          </view>
+        </view>
+      </view>
+
+      <text class="title">
+        使用单位:
+        <text class="text">{{ item.unitName }}</text>
+      </text>
+      <view class="row-center">
+        <text class="title">
+          项目负责人:
+          <text class="text">{{ item?.manager?.nickname }}</text>
+        </text>
+        <text class="title">
+          主检人:
+          <text class="text">{{ item?.mainCheckerUser?.nickname }}</text>
+        </text>
+      </view>
+      <text class="title">
+        检验员:
+        <text class="text">{{ checkUsersText }}</text>
+      </text>
+      <text class="title">
+        检验项目:
+        <text class="text">{{ reportText }}</text>
+      </text>
+    </view>
+
+    <view class="btn-group">
+      <button class="main-btn" @click="handleOperation">
+          <text class="main-btn-text">{{ operateText }}</text>
+      </button>
+    </view>
+
+  </view>
+</template>
+
+<script lang="ts" setup>
+import { computed } from 'vue'
+import { PipeCheckTypeMap } from '@/utils/dictMap'
+import { PressureCheckerMyTaskStatusMap } from '@/utils/dictMap'
+
+interface Props {
+  item: any
+  reportDOList: any[]
+  operateText: string
+}
+
+const props = defineProps<Props>()
+
+const emit = defineEmits<{
+  handleOperation: [item: any, reportDOList: any]
+}>()
+
+const checkType = computed(() => {
+  return PipeCheckTypeMap[props.item.checkType] || ''
+})
+
+const checkTypeColor = computed(() => {
+  switch (props.item.checkType) {
+    case 200:
+      return 'rgb(251,127,55)'
+    case 300:
+      return '#ff4d4f'
+    default:
+      return '#2F8EFF'
+  }
+})
+
+const checkDate = computed(() => {
+  return props.item.checkDate ? props.item.checkDate.join('-') : ''
+})
+
+const checkUsersText = computed(() => {
+  const checkUsers = props.item?.checkUsers?.map((check: any) => check.nickname)
+  return checkUsers?.length > 0 ? checkUsers.join(',') : ''
+})
+
+const reportText = computed(() => {
+  return props.reportDOList?.map((item) => item.reportName)?.join('、') || ''
+})
+
+const taskStatusText = computed(() => {
+  return PressureCheckerMyTaskStatusMap[props.item.taskStatus] || ''
+})
+
+const handleOperation = () => {
+  emit('handleOperation', props.item, props.reportDOList)
+}
+</script>
+
+<style lang="scss" scoped>
+.item-box {
+  margin: 13px;
+  padding: 13px;
+  background-color: #fff;
+  border-radius: 5px;
+}
+
+.row {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+
+.item-top {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  align-items: center;
+  border-bottom: 1px solid rgb(244, 244, 244);
+  padding-bottom: 10px;
+  margin-bottom: 10px;
+}
+
+.item-top-left {
+  flex: 1;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.item-top-text {
+  font-size: 17px;
+  color: rgb(51, 51, 51);
+  font-weight: bold;
+}
+
+.item-top-num-box {
+  border-radius: 2px;
+  background-color: rgb(255, 227, 210);
+  padding: 3px;
+  min-width: 46px;
+  text-align: center;
+  font-size: 12px;
+  color: rgb(251, 127, 55);
+}
+
+.main-btn {
+  width: 82px;
+  height: 29px;
+  border-radius: 3px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: rgb(47, 142, 255);
+  margin: 0;
+  border: none;
+  padding: 0;
+}
+
+.main-btn-text {
+  color: rgb(222, 238, 255);
+  font-size: 15px;
+}
+
+.item-center {
+  display: flex;
+  flex-direction: column;
+  padding: 8px 12px;
+  background-color: rgb(244, 244, 244);
+  border-radius: 5px;
+}
+
+.row-center {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.title {
+  color: rgb(108, 108, 108);
+  font-size: 12px;
+  line-height: 25px;
+  margin-right: 5px;
+}
+
+.text {
+  color: rgb(51, 51, 51);
+  font-size: 12px;
+  line-height: 25px;
+}
+
+.status-badge {
+  height: 25px;
+  padding: 0 5px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #ffe3d2;
+  border-radius: 3px;
+}
+
+.status-text {
+  color: rgb(251, 127, 55);
+  font-size: 12px;
+}
+
+.btn-group {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: flex-end;
+  margin-top: 10px;
+}
+</style>

+ 1 - 1
src/pages/taskOnlinePage/components/query/CheckNatureCom.vue

@@ -68,7 +68,7 @@ const columns = computed(() => {
 
 const displayLabel = computed(() => {
   if (selectCode.value == null) return ''
-  const item = columns.find((c) => c.value === selectCode.value)
+  const item = columns.value.find((c) => c.value === selectCode.value)
   return item ? item.label : ''
 })
 

+ 2 - 0
src/types/uni-pages.d.ts

@@ -39,8 +39,10 @@ interface NavigateToOptions {
        "/pages/pendingPreparation/preViewReport/index" |
        "/pages/pendingRatify/list/PendingRatifyList" |
        "/pages/pendingRatify/preViewReport/index" |
+       "/pages/pendingVerification/list/BoilerItem" |
        "/pages/pendingVerification/list/Item" |
        "/pages/pendingVerification/list/PendingVerificationList" |
+       "/pages/pendingVerification/list/PipeItem" |
        "/pages/pendingVerification/preViewReport/index" |
        "/pages/securityCheck/detail/index" |
        "/pages/workInstructionAudit/list/WorkInstructionAuditList" |