2026-08-18 18:05:16 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="search-page">
|
2026-08-20 17:53:59 +08:00
|
|
|
|
<!-- 顶部固定筛选:扫码 + 管线号/焊口号 + 重置/查询 -->
|
|
|
|
|
|
<view class="filter-panel">
|
|
|
|
|
|
<view class="filter-panel__row">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="filter-panel__scan"
|
2026-08-18 18:05:16 +08:00
|
|
|
|
@click="handleScan"
|
2026-08-20 17:53:59 +08:00
|
|
|
|
>
|
|
|
|
|
|
<u-icon
|
|
|
|
|
|
name="scan"
|
|
|
|
|
|
:size="36"
|
|
|
|
|
|
color="#2979ff"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="filter-panel__fields">
|
|
|
|
|
|
<view class="filter-panel__item filter-panel__item--pipe">
|
|
|
|
|
|
<input
|
|
|
|
|
|
class="filter-panel__input"
|
|
|
|
|
|
v-model="pipelineCode"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="管线号"
|
|
|
|
|
|
confirm-type="search"
|
|
|
|
|
|
@confirm="handleSearch"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="filter-panel__item filter-panel__item--joint">
|
|
|
|
|
|
<input
|
|
|
|
|
|
class="filter-panel__input"
|
|
|
|
|
|
v-model="weldJointCode"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="焊口号"
|
|
|
|
|
|
confirm-type="search"
|
|
|
|
|
|
@confirm="handleSearch"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="filter-panel__actions">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="filter-panel__btn filter-panel__btn--reset"
|
|
|
|
|
|
@click="handleReset"
|
|
|
|
|
|
>重置</view>
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="filter-panel__btn filter-panel__btn--search"
|
|
|
|
|
|
@click="handleSearch"
|
|
|
|
|
|
>查询</view>
|
2026-08-18 18:05:16 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 结果列表 -->
|
|
|
|
|
|
<scroll-view
|
|
|
|
|
|
class="result-scroll"
|
|
|
|
|
|
scroll-y
|
|
|
|
|
|
@scrolltolower="loadMore"
|
|
|
|
|
|
>
|
|
|
|
|
|
<view class="result-list">
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(item, index) in listData"
|
|
|
|
|
|
:key="item.WeldJointId || item.Id || index"
|
|
|
|
|
|
class="result-item"
|
|
|
|
|
|
@click="handleSelect(item)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<view class="result-item__main">
|
|
|
|
|
|
<text class="result-item__code">{{ item.WeldJointCode || '--' }}</text>
|
|
|
|
|
|
<text
|
|
|
|
|
|
v-if="item.PipelineCode"
|
|
|
|
|
|
class="result-item__sub"
|
|
|
|
|
|
>管线 {{ item.PipelineCode }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<u-icon
|
|
|
|
|
|
name="arrow-right"
|
|
|
|
|
|
:size="24"
|
|
|
|
|
|
color="#ccc"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<u-empty
|
|
|
|
|
|
v-if="!loading && searched && listData.length === 0"
|
|
|
|
|
|
mode="search"
|
|
|
|
|
|
text="未找到焊口"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-if="!searched && !loading"
|
|
|
|
|
|
class="result-hint"
|
|
|
|
|
|
>
|
2026-08-20 17:53:59 +08:00
|
|
|
|
<text>扫码,或输入管线号 / 焊口号后点击查询</text>
|
2026-08-18 18:05:16 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-if="loading && listData.length > 0"
|
|
|
|
|
|
class="loading-more"
|
|
|
|
|
|
>
|
|
|
|
|
|
<u-loading
|
|
|
|
|
|
mode="circle"
|
|
|
|
|
|
size="28"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<text>加载中...</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-if="!loading && !hasMore && listData.length > 0"
|
|
|
|
|
|
class="no-more"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text>— 没有更多了 —</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
/**
|
2026-08-20 17:53:59 +08:00
|
|
|
|
* 焊口搜索中间页:扫码进入业务页,或按管线号/焊口号搜索后点选进入
|
2026-08-18 18:05:16 +08:00
|
|
|
|
* 入参:target(业务页路径)、title(导航标题)
|
|
|
|
|
|
*/
|
|
|
|
|
|
import { ref } from 'vue'
|
|
|
|
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
|
|
|
|
import { storeToRefs } from 'pinia'
|
|
|
|
|
|
import { useUserStore, useMenuStore } from '@/store'
|
|
|
|
|
|
import { getUrlParam } from '@/utils/request.js'
|
|
|
|
|
|
import { reqPipeJointWeldedJoints } from '@/api/hj.js'
|
|
|
|
|
|
|
|
|
|
|
|
const userStore = useUserStore()
|
|
|
|
|
|
const menuStore = useMenuStore()
|
|
|
|
|
|
const { currentProject } = storeToRefs(userStore)
|
|
|
|
|
|
|
|
|
|
|
|
/** 业务目标页,如 /scanpages/hj/material_sampling */
|
|
|
|
|
|
const targetPath = ref('')
|
|
|
|
|
|
|
2026-08-20 17:53:59 +08:00
|
|
|
|
const pipelineCode = ref('')
|
|
|
|
|
|
const weldJointCode = ref('')
|
2026-08-18 18:05:16 +08:00
|
|
|
|
const listData = ref([])
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
const searched = ref(false)
|
|
|
|
|
|
const hasMore = ref(true)
|
|
|
|
|
|
const currentPage = ref(1)
|
|
|
|
|
|
const pageSize = 20
|
2026-08-20 17:53:59 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 是否有可搜索条件
|
|
|
|
|
|
*/
|
|
|
|
|
|
const hasKeyword = () => !!(pipelineCode.value.trim() || weldJointCode.value.trim())
|
2026-08-18 18:05:16 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 从接口响应取出列表
|
|
|
|
|
|
* @param {any} data
|
|
|
|
|
|
*/
|
|
|
|
|
|
const pickList = (data) => {
|
|
|
|
|
|
if (!data) return []
|
|
|
|
|
|
if (Array.isArray(data)) return data
|
|
|
|
|
|
if (Array.isArray(data.getDataList)) return data.getDataList
|
|
|
|
|
|
if (Array.isArray(data.list)) return data.list
|
|
|
|
|
|
if (Array.isArray(data.records)) return data.records
|
|
|
|
|
|
if (Array.isArray(data.Items)) return data.Items
|
|
|
|
|
|
return []
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const clearList = () => {
|
|
|
|
|
|
listData.value = []
|
|
|
|
|
|
hasMore.value = false
|
|
|
|
|
|
searched.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 拉取焊口列表
|
|
|
|
|
|
* @param {boolean} isRefresh
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadList = async (isRefresh = true) => {
|
|
|
|
|
|
const projectId = currentProject.value?.ProjectId
|
|
|
|
|
|
if (!projectId) {
|
|
|
|
|
|
uni.showToast({ title: '请先选择项目', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-08-20 17:53:59 +08:00
|
|
|
|
if (!hasKeyword()) {
|
|
|
|
|
|
uni.showToast({ title: '请输入管线号或焊口号', icon: 'none' })
|
2026-08-18 18:05:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if (loading.value) return
|
|
|
|
|
|
if (!isRefresh && !hasMore.value) return
|
|
|
|
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
if (isRefresh) {
|
|
|
|
|
|
currentPage.value = 1
|
|
|
|
|
|
hasMore.value = true
|
|
|
|
|
|
listData.value = []
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await reqPipeJointWeldedJoints({
|
|
|
|
|
|
projectId,
|
2026-08-20 17:53:59 +08:00
|
|
|
|
pipelineCode: pipelineCode.value.trim() || undefined,
|
|
|
|
|
|
weldJointCode: weldJointCode.value.trim() || undefined,
|
2026-08-18 18:05:16 +08:00
|
|
|
|
pageIndex: currentPage.value,
|
|
|
|
|
|
pageSize,
|
|
|
|
|
|
})
|
|
|
|
|
|
const data = res?.data ?? {}
|
|
|
|
|
|
const pageData = pickList(data)
|
|
|
|
|
|
const totalPages = Number(data.pageCount) || 0
|
|
|
|
|
|
const totalCount = Number(data.totalCount) || 0
|
|
|
|
|
|
if (totalPages > 0) {
|
|
|
|
|
|
hasMore.value = currentPage.value < totalPages
|
|
|
|
|
|
} else if (totalCount > 0) {
|
|
|
|
|
|
hasMore.value = listData.value.length + pageData.length < totalCount
|
|
|
|
|
|
} else {
|
|
|
|
|
|
hasMore.value = pageData.length >= pageSize
|
|
|
|
|
|
}
|
|
|
|
|
|
listData.value = isRefresh ? pageData : listData.value.concat(pageData)
|
|
|
|
|
|
searched.value = true
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('焊口搜索失败:', e)
|
|
|
|
|
|
if (isRefresh) listData.value = []
|
|
|
|
|
|
searched.value = true
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-20 17:53:59 +08:00
|
|
|
|
/** 点击查询 */
|
|
|
|
|
|
const handleSearch = () => {
|
2026-08-18 18:05:16 +08:00
|
|
|
|
loadList(true)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-20 17:53:59 +08:00
|
|
|
|
/** 重置条件与结果 */
|
|
|
|
|
|
const handleReset = () => {
|
|
|
|
|
|
pipelineCode.value = ''
|
|
|
|
|
|
weldJointCode.value = ''
|
2026-08-18 18:05:16 +08:00
|
|
|
|
clearList()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const loadMore = () => {
|
2026-08-20 17:53:59 +08:00
|
|
|
|
if (!loading.value && hasMore.value && hasKeyword()) {
|
2026-08-18 18:05:16 +08:00
|
|
|
|
currentPage.value += 1
|
|
|
|
|
|
loadList(false)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 进入业务页
|
|
|
|
|
|
* @param {string} id WeldJointId
|
|
|
|
|
|
*/
|
|
|
|
|
|
const goTarget = (id) => {
|
|
|
|
|
|
if (!id) {
|
|
|
|
|
|
uni.showToast({ title: '缺少焊口信息', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!targetPath.value) {
|
|
|
|
|
|
uni.showToast({ title: '缺少目标页面', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!menuStore.canAccessPath(targetPath.value)) {
|
|
|
|
|
|
uni.showToast({ title: '当前岗位无此功能权限', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
|
url: `${targetPath.value}?id=${encodeURIComponent(id)}`
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 点选搜索结果
|
|
|
|
|
|
* @param {object} item
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleSelect = (item) => {
|
|
|
|
|
|
const id = item.WeldJointId || item.Id || item.id
|
|
|
|
|
|
goTarget(id)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 扫码:与首页菜单扫码一致,解析 id 后进入业务页
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleScan = () => {
|
|
|
|
|
|
uni.scanCode({
|
|
|
|
|
|
scanType: ['datamatrix', 'barCode', 'qrCode', 'wxCode', 'pdf417'],
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
const result = res.result || ''
|
|
|
|
|
|
let id = getUrlParam(result, 'id')
|
|
|
|
|
|
if (!id) {
|
|
|
|
|
|
id = String(result).trim()
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!id) {
|
|
|
|
|
|
uni.showToast({ title: '未识别到焊口', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
goTarget(id)
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
if (err?.errMsg && String(err.errMsg).includes('cancel')) return
|
|
|
|
|
|
uni.showToast({ title: '扫码失败,请重试', icon: 'none' })
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onLoad((opt) => {
|
|
|
|
|
|
targetPath.value = decodeURIComponent(opt.target || '')
|
|
|
|
|
|
const title = opt.title ? decodeURIComponent(opt.title) : '选择焊口'
|
|
|
|
|
|
uni.setNavigationBarTitle({ title })
|
|
|
|
|
|
if (!targetPath.value) {
|
|
|
|
|
|
uni.showToast({ title: '入口参数错误', icon: 'none' })
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.search-page {
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
background: #f5f6f8;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-20 17:53:59 +08:00
|
|
|
|
.filter-panel {
|
|
|
|
|
|
flex-shrink: 0;
|
2026-08-18 18:05:16 +08:00
|
|
|
|
padding: 16rpx 24rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
position: sticky;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
z-index: 10;
|
|
|
|
|
|
|
2026-08-20 17:53:59 +08:00
|
|
|
|
&__row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__scan {
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
width: 72rpx;
|
2026-08-18 18:05:16 +08:00
|
|
|
|
height: 72rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-08-20 17:53:59 +08:00
|
|
|
|
justify-content: center;
|
|
|
|
|
|
background: #f5f6f8;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__fields {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-08-18 18:05:16 +08:00
|
|
|
|
gap: 12rpx;
|
2026-08-20 17:53:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__item {
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
height: 72rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 0 16rpx;
|
2026-08-18 18:05:16 +08:00
|
|
|
|
background: #f5f6f8;
|
2026-08-20 17:53:59 +08:00
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
|
|
|
|
|
|
&--pipe {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--joint {
|
|
|
|
|
|
flex: none;
|
|
|
|
|
|
width: 140rpx;
|
|
|
|
|
|
}
|
2026-08-18 18:05:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__input {
|
|
|
|
|
|
flex: 1;
|
2026-08-20 17:53:59 +08:00
|
|
|
|
min-width: 0;
|
|
|
|
|
|
height: 72rpx;
|
2026-08-18 18:05:16 +08:00
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333;
|
2026-08-20 17:53:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
margin-top: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__btn {
|
|
|
|
|
|
flex: 1;
|
2026-08-18 18:05:16 +08:00
|
|
|
|
height: 72rpx;
|
2026-08-20 17:53:59 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
|
|
|
|
|
|
&--reset {
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
background: #f5f6f8;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--search {
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
background: #2979ff;
|
|
|
|
|
|
}
|
2026-08-18 18:05:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.result-scroll {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
height: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.result-list {
|
|
|
|
|
|
padding: 16rpx 24rpx 40rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.result-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
padding: 28rpx 24rpx;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
|
|
|
|
|
|
&__main {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__code {
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #1a2332;
|
|
|
|
|
|
font-family: monospace;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&__sub {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.result-hint {
|
|
|
|
|
|
padding: 80rpx 0;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #bbb;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.loading-more,
|
|
|
|
|
|
.no-more {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
|
padding: 24rpx;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|