Files
sh-app/pages/index/index.vue
T

332 lines
9.1 KiB
Vue
Raw Normal View History

2026-06-09 19:29:04 +08:00
<template>
<view class="wrap home">
2026-06-16 19:26:48 +08:00
<view class="home-navbar">
2026-06-09 19:29:04 +08:00
<view class="slot-wrap">
<u-input style="color: #ffffff;" v-model="currentProjectName" :clearable="false" type="select"
placeholder="请选择项目" @click="handleShowProjectSelect" />
</view>
2026-06-16 19:26:48 +08:00
<view class="home-navbar-title">首页</view>
<view class="home-navbar-placeholder"></view>
</view>
2026-06-09 19:29:04 +08:00
<view class="home-icons">
2026-06-10 14:17:54 +08:00
2026-06-09 19:29:04 +08:00
<view class="home-icon" @click="handleScan">
<u-icon name="saoyisao" custom-prefix="nbd-icon" :size="68" color="#ffffff" />
<text>扫一扫</text>
</view>
2026-06-16 19:26:48 +08:00
<view class="home-icon" @click="handleSkipByPath('/pages/todo/list')">
2026-06-09 19:29:04 +08:00
<u-icon name="daiban" custom-prefix="nbd-icon" :size="68" color="#ffffff" />
<text>待办</text>
</view>
</view>
2026-06-18 15:10:50 +08:00
<scroll-view class="home-scroll" scroll-y>
<view class="home-hj">
<view class="hj-content">
<view class="hj-row">
<view class="hj-cell">
<text class="hj-label">工厂焊接一次合格率</text>
<text class="hj-value">{{ hjIndexData?.GCFirstPassRate|| '--'}}</text>
</view>
<view class="hj-cell">
<text class="hj-label">现场焊接一次合格率</text>
<text class="hj-value">{{ hjIndexData?.XCFirstPassRate || '--' }}</text>
</view>
2026-06-09 19:29:04 +08:00
</view>
2026-06-18 15:10:50 +08:00
<view class="hj-row">
<view class="hj-cell">
<text class="hj-label">工厂预制进度</text>
<text class="hj-value hj-sub">{{ hjIndexData?.GCProgress|| '--' }}</text>
</view>
<view class="hj-cell">
<text class="hj-label">现场焊接进度</text>
<text class="hj-value hj-sub">{{ hjIndexData?.XCProgress || '--'}}</text>
</view>
2026-06-09 19:29:04 +08:00
</view>
2026-06-18 15:10:50 +08:00
<view class="hj-row">
<view class="hj-cell">
<text class="hj-label">工厂焊工功效</text>
<text class="hj-value">{{ hjIndexData?.GCWelderEfficacy || '--'}}</text>
</view>
<view class="hj-cell">
<text class="hj-label">现场焊接功效</text>
<text class="hj-value">{{ hjIndexData?.XCWelderEfficacy || '--'}}</text>
</view>
2026-06-09 19:29:04 +08:00
</view>
</view>
2026-06-18 15:10:50 +08:00
<view class="hj-footer">
<text class="hj-footer-label">项目管道实时预制率 (包含工厂和现场的预制口)</text>
<text class="hj-footer-value">{{ hjIndexData?.PipePrefabricationRate || '--'}}</text>
2026-06-09 19:29:04 +08:00
</view>
</view>
2026-06-18 15:10:50 +08:00
<!-- 快捷应用 -->
<view class="section-card home-quick">
<view class="section-title">
<view class="title-left">
<text class="title-line"></text>
<text>快捷应用</text>
</view>
<u-icon class="edit-btn" name="edit-pen" :size="32" color="#999" @click="openEditQuick" />
2026-06-10 14:17:54 +08:00
</view>
2026-06-18 15:10:50 +08:00
<view class="section-grid">
<view class="grid-item" v-for="(item, idx) in quickApps" :key="idx" @click="handleSkip(item)">
<view class="icon-box">
<u-icon :name="item.icon" :size="56" :custom-prefix='item.prefix'
:color="pastelColors[idx % 6]" />
</view>
<text class="item-label">{{ item.name }}</text>
2026-06-10 14:17:54 +08:00
</view>
2026-06-18 15:10:50 +08:00
<view v-if="quickApps.length === 0" class="empty-tip">请选择应用</view>
2026-06-10 14:17:54 +08:00
</view>
</view>
2026-06-18 15:10:50 +08:00
<!-- 业务查询 -->
<view class="section-card home-query" v-if="queryApps && queryApps.length > 0">
<view class="section-title">
<view class="title-left">
<text class="title-line"></text>
<text>业务查询</text>
</view>
2026-06-10 14:17:54 +08:00
</view>
2026-06-18 15:10:50 +08:00
<view class="section-grid">
<view class="grid-item" v-for="(item, idx) in queryApps" :key="idx" @click="handleSkip(item)">
<view class="icon-box">
<u-icon :name="item.icon" :custom-prefix='item.prefix' :size="56"
:color="pastelColors[idx % 6]" />
</view>
<text class="item-label">{{ item.name }}</text>
2026-06-10 14:17:54 +08:00
</view>
</view>
</view>
2026-06-18 15:10:50 +08:00
</scroll-view>
2026-06-10 14:17:54 +08:00
<!-- 编辑快捷应用弹窗 -->
2026-06-18 15:10:50 +08:00
<u-popup v-model="showEditQuick" mode="bottom" height="75%">
2026-06-10 14:17:54 +08:00
<view class="edit-quick">
<view class="edit-title">
<text>选择快捷应用</text>
</view>
2026-06-18 15:10:50 +08:00
<view class="edit-search">
<u-icon name="search" :size="28" color="#999" />
<input class="edit-search__input" v-model="keyword" placeholder="搜索应用名称" confirm-type="search" />
</view>
2026-06-24 20:50:15 +08:00
<scroll-view class="edit-scroll" scroll-y>
<view class="edit-grid">
<view v-for="(item, idx) in filteredEditCache" :key="idx" class="edit-item"
:class="{ active: item.selected }" @click="toggleSelect(item)">
<view class="icon-box">
<u-icon :name="item.icon" :size="48" :custom-prefix='item.prefix'
:color="item.selected ? pastelColors[idx % 6] : '#ccc'" />
</view>
<text class="edit-label">{{ item.name }}</text>
<view v-if="item.selected" class="selected-mark">
<u-icon name="checkmark" :size="24" color="#fff" />
</view>
2026-06-10 14:17:54 +08:00
</view>
2026-06-24 20:50:15 +08:00
<view v-if="filteredEditCache.length === 0" class="edit-empty">
<text>没有匹配的应用</text>
2026-06-10 14:17:54 +08:00
</view>
</view>
2026-06-18 15:10:50 +08:00
</scroll-view>
2026-06-10 14:17:54 +08:00
<view class="edit-btns">
<u-button size="medium" class="btn-cancel" @click="showEditQuick = false">取消</u-button>
<u-button size="medium" class="btn-confirm" type="primary" @click="handleConfirmEdit">确定</u-button>
</view>
</view>
</u-popup>
2026-06-10 17:26:36 +08:00
<nbd-select v-model="showProject" title="请选择项目" :list="projectList" label-key="ProjectName" :show-search="true"
2026-06-11 14:11:56 +08:00
value-key="ProjectId" v-model:model="currentProject" @search-change="handleSearchChange"
2026-06-10 17:26:36 +08:00
@confirm="handleConfirmProject" />
2026-06-09 19:29:04 +08:00
</view>
</template>
<script setup>
import {
reqProjectByUserId
} from '@/api/user.js'
import {
computed,
reactive,
ref
} from 'vue'
import {
2026-06-10 14:17:54 +08:00
useUserStore,
useMenuStore,
useLargeStore
2026-06-09 19:29:04 +08:00
} from '@/store';
2026-06-10 14:17:54 +08:00
2026-06-09 19:29:04 +08:00
import {
storeToRefs
} from 'pinia';
2026-06-11 09:43:42 +08:00
import {
2026-06-18 15:10:50 +08:00
parseScanResult
2026-06-11 09:43:42 +08:00
} from '@/utils/scanUtils.js'
2026-06-18 15:10:50 +08:00
import {
getUrlParam
} from '@/utils/request.js'
2026-06-11 09:43:42 +08:00
2026-06-09 19:29:04 +08:00
const userStore = useUserStore()
2026-06-10 14:17:54 +08:00
const menuStore = useMenuStore()
const largeStore = useLargeStore()
2026-06-09 19:29:04 +08:00
const {
setProjectList,
setCurrentProject
} = userStore
const {
userInfo,
projectList,
currentProject
} = storeToRefs(userStore)
2026-06-10 14:17:54 +08:00
const {
quickApps,
queryApps,
editCache
} = storeToRefs(menuStore)
const {
hjIndexData
} = storeToRefs(largeStore)
const {
pastelColors
} = menuStore
const projectNameKeyword = ref('')
2026-06-09 19:29:04 +08:00
const showProject = ref(false)
2026-06-10 14:17:54 +08:00
const showEditQuick = ref(false)
2026-06-18 15:10:50 +08:00
const keyword = ref('')
2026-06-10 14:17:54 +08:00
const currentProjectName = computed(() => currentProject.value?.ProjectName || '')
2026-06-18 15:10:50 +08:00
// 搜索过滤后的编辑列表
const filteredEditCache = computed(() => {
const kw = keyword.value.trim().toLowerCase()
if (!kw) return editCache.value
return editCache.value.filter(item => item.name.toLowerCase().includes(kw))
})
2026-06-10 17:26:36 +08:00
const handleSkip = (item) => {
2026-06-11 09:43:42 +08:00
if (!currentProject.value.ProjectId) {
2026-06-10 17:26:36 +08:00
handleShowProjectSelect()
uni.showToast({
title: '请选择一个项目',
icon: 'none'
})
return
}
2026-06-18 15:10:50 +08:00
if (item.isScan) {
handleMenuScan(item.path)
return
}
2026-06-10 14:17:54 +08:00
uni.navigateTo({
url: item.path
})
}
// 打开编辑弹窗
const openEditQuick = () => {
menuStore.openEdit()
2026-06-18 15:10:50 +08:00
keyword.value = ''
2026-06-10 14:17:54 +08:00
showEditQuick.value = true
}
// 切换选择状态
const toggleSelect = (item) => {
menuStore.toggleSelect(item)
}
// 确认编辑
const handleConfirmEdit = () => {
menuStore.confirmEdit()
showEditQuick.value = false
uni.showToast({
title: '已更新快捷应用',
2026-06-10 17:26:36 +08:00
icon: 'none'
2026-06-10 14:17:54 +08:00
})
}
2026-06-09 19:29:04 +08:00
const handleShowProjectSelect = () => {
reqProjectByUserId(userInfo.value.PersonId).then(res => {
setProjectList(res.data)
showProject.value = true
})
}
/**
* 项目列表点击确认
*/
2026-06-10 14:17:54 +08:00
const handleConfirmProject = (item) => {
2026-06-09 19:29:04 +08:00
setCurrentProject(item)
showProject.value = false
}
2026-06-10 14:17:54 +08:00
/**
* 项目按名称搜索
*/
const handleSearchChange = (keyword) => {
projectNameKeyword.value = keyword
}
2026-06-18 15:10:50 +08:00
/**
* 菜单扫一扫
*/
const handleMenuScan = (path) => {
wx.scanCode({
scanType: ['datamatrix', 'barCode', 'qrCode', 'wxCode', 'pdf417'],
success(res) {
// 获取路径给的ID
let id = getUrlParam(res.result, 'id')
uni.navigateTo({
url: path + (id ? `?id=${id}` : '')
})
},
fail(err) {
console.log(err)
uni.showToast({
title: '扫码失败,请重试',
icon: 'none'
})
}
})
}
2026-06-09 19:29:04 +08:00
/**
* 扫一扫
*/
2026-06-10 14:17:54 +08:00
const handleScan = () => {
2026-06-18 15:10:50 +08:00
// 调起条码扫描
wx.scanCode({
scanType: ['datamatrix', 'barCode', 'qrCode', 'wxCode', 'pdf417'],
2026-06-10 14:17:54 +08:00
success(res) {
2026-06-18 15:10:50 +08:00
console.log('扫码结果==>', res)
if (res.scanType != 'QR_CODE') {
uni.navigateTo({
url: '/scanpages/hj/materials_detail?id=' + res.result
})
}
if (res.scanType == 'QR_CODE') {
const result = res.result || ''
// 优先按 URL 规则解析(焊接接头等)
const parsed = parseScanResult(result)
if (parsed) {
uni.navigateTo({
url: `${parsed.path}?${parsed.query}`
})
return
}else{
uni.showToast({
title: '无对应业务',
icon: 'none'
})
}
2026-06-16 19:26:48 +08:00
}
2026-06-09 19:29:04 +08:00
},
fail(err) {
2026-06-18 15:10:50 +08:00
console.log(err)
uni.showToast({
title: '扫码失败,请重试',
icon: 'none'
})
2026-06-09 19:29:04 +08:00
}
2026-06-11 09:43:42 +08:00
})
2026-06-09 19:29:04 +08:00
}
2026-06-10 14:17:54 +08:00
</script>