站内台账库存

This commit is contained in:
hongchao 2025-09-18 18:52:14 +08:00
parent a94ddc0a70
commit c839a6872a
5 changed files with 1031 additions and 0 deletions

View File

@ -947,6 +947,20 @@
"style": {
"navigationBarTitleText": "安全工器具预警"
}
},
//
{
"path": "pages/materialsStation/equipmentRecord/equipmentRecord",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/materialsStation/equipmentRecord/equipmentRecordDetails",
"style": {
"navigationStyle": "custom"
}
}
// end
],

View File

@ -0,0 +1,581 @@
<template>
<uni-nav-bar dark :fixed="true" shadow background-color="#4AA4EA" status-bar :title="title">
<template v-slot:left>
<view style="font-size: 18px; display: flex; align-items: center" @click="back">
<uni-icons type="left" size="20" color="#fff"></uni-icons>
<text>返回</text>
</view>
</template>
</uni-nav-bar>
<div class="content">
<div class="card">
<uni-row
:gutter="30"
style="display: flex; align-items: center; margin-top: 5px;"
>
<uni-col :span="15">
<uni-forms-item name="impUnitName" >
<uni-data-select
v-model="queryParams.impUnitName"
:localdata="impUnitOptions"
@change="handleImpUnitChange"
placeholder="选择分公司"
:searchable="false"
filterable
></uni-data-select>
</uni-forms-item>
</uni-col>
<uni-col :span="15">
<uni-forms-item name="departName" >
<uni-data-select
v-model="queryParams.departName"
:localdata="departOptions"
@change="handleDepartChange"
placeholder="选择项目部"
:searchable="false"
filterable
></uni-data-select>
</uni-forms-item>
</uni-col>
</uni-row>
<uni-row
:gutter="30"
style="display: flex; "
>
<uni-col :span="24">
<uni-forms-item name="proName" >
<uni-data-select
v-model="queryParams.proName"
:localdata="proOptions"
placeholder="选择工程"
:searchable="false"
filterable
></uni-data-select>
</uni-forms-item>
</uni-col>
<uni-col :span="6">
<view class="addBtn" @click="getList">查询</view>
</uni-col>
</uni-row>
</div>
<scroll-view scroll-y class="scroll-container">
<div class="equipment-list">
<!-- 一级分公司 -->
<div
v-for="(category, categoryIndex) in filteredEquipmentCategories"
:key="categoryIndex"
class="equipment-category-section"
>
<!-- 分公司标题 -->
<div class="equipment-category" @click="toggleCategory(categoryIndex)">
<span>{{ category.impUnitName }} <span class="count">{{ category.departNameList?category.departNameList.length:0 }}</span></span>
<uni-icons
:type="category.expanded ? 'top' : 'bottom'"
size="16"
color="#999"
class="expand-icon"
></uni-icons>
</div>
<!-- 二级项目部 -->
<div v-if="category.expanded" class="project-section">
<div
v-for="(project, projectIndex) in category.departNameList"
:key="projectIndex"
class="project-item"
>
<!-- 项目部标题 -->
<div class="project-title" @click="toggleProject(categoryIndex, projectIndex)">
<span>{{ project.departName }} <span class="count">{{ project.departNameList?project.departNameList.length:0 }}</span></span>
<uni-icons
:type="project.expanded ? 'top' : 'bottom'"
size="14"
color="#999"
class="expand-icon-small"
></uni-icons>
</div>
<!-- 三级工程列表 -->
<div v-if="project.expanded" class="engineering-list">
<div
v-for="(engineering, engineeringIndex) in project.departNameList"
:key="engineeringIndex"
class="engineering-item"
@click="showDetail(engineering)"
>
<div class="engineering-info">
<div class="engineering-name">{{ engineering.proName }}</div>
<!-- <div class="engineering-spec">库存: {{ engineering.storeNum }} | 单价: {{ engineering.buyPrice }}</div> -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
style="
display: flex;
justify-content: center;
align-items: center;
height: 50px;
margin: 10px 0;
"
>
<!-- {{ '没有更多数据了~' }} -->
</div>
</scroll-view>
</div>
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { onMounted, ref, reactive, computed } from 'vue'
import { getBranchListApi,getImpUnitListApi, getDepartListByImpUnitApi, getProListByDepartApi, } from '@/services/materialsStation'
import { useMemberStore } from '@/stores'
const memberStore = useMemberStore()
const userInfo = ref(memberStore.userInfo || {})
const title = ref('站内库存台账')
const searchText = ref('')
const queryParams = ref({
impUnitName: '',
departName: '',
proName: '',
keyWord: '',
})
const impUnitOptions = ref([])
const departOptions = ref([])
const proOptions = ref([])
const back = () => {
uni.navigateBack({
delta: 1,
})
}
//
const equipmentCategories = ref([
{
typeName: '分公司1',
expanded: false, //
modelList: [
{ typeModelName: '项目部1', storeNum: 10, manageType: '编码', buyPrice: 100, typeId: 1,expanded: false, //
modelList: [
{ typeModelName: '工程1', storeNum: 5, manageType: '编码', buyPrice: 100, typeId: 1 },
{ typeModelName: '工程2', storeNum: 5, manageType: '编码', buyPrice: 100, typeId: 2 },
]
},
{ typeModelName: '项目部2', storeNum: 20, manageType: '编码', buyPrice: 150, typeId: 2,expanded: false, //
modelList: [
{ typeModelName: '工程3', storeNum: 5, manageType: '编码', buyPrice: 100, typeId: 1 },
// { typeModelName: '4', storeNum: 5, manageType: '', buyPrice: 100, typeId: 2 },
]
},
]
},
{
typeName: '分公司2',
expanded: false, //
modelList: [
{ typeModelName: '项目部1', storeNum: 10, manageType: '编码', buyPrice: 100, typeId: 1,expanded: false, //
modelList: [
{ typeModelName: '工程1', storeNum: 5, manageType: '编码', buyPrice: 100, typeId: 1 },
{ typeModelName: '工程2', storeNum: 5, manageType: '编码', buyPrice: 100, typeId: 2 },
]
},
{ typeModelName: '项目部2', storeNum: 20, manageType: '编码', buyPrice: 150, typeId: 2,expanded: false, //
modelList: [
{ typeModelName: '工程3', storeNum: 5, manageType: '编码', buyPrice: 100, typeId: 1 },
{ typeModelName: '工程4', storeNum: 5, manageType: '编码', buyPrice: 100, typeId: 2 },
]
},
]
}
])
onLoad((opt) => {
console.log('🚀 ~ onLoad ~ opt:', opt)
getImpUnitOptions()
handleImpUnitChange()
handleDepartChange()
getList()
})
onMounted(() => {
// getList()
})
/** 获取分公司下拉 */
const getImpUnitOptions= async () => {
try {
const res = await getImpUnitListApi() //
impUnitOptions.value = res.data.map(item => ({
text: item.impUnitName, //
value: item.impUnitName
}))
} catch (e) {
console.error('获取分公司下拉失败:', e)
}
};
/** 分公司选择变化,加载项目部 */
const handleImpUnitChange= async () => {
queryParams.value.departName = null //
departOptions.value = [] //
try {
const params = {
impUnitName: queryParams.value.impUnitName, //
departName: queryParams.value.departName, //
proName: queryParams.value.proName,
}
const res = await getDepartListByImpUnitApi(params)
departOptions.value = res.data.map(item => ({
text: item.departName, //
value: item.departName
}))
} catch (e) {
console.error('获取项目部下拉失败:', e)
}
};
/** 项目部选择变化,加载工程 */
const handleDepartChange= async () => {
queryParams.value.proName = null //
proOptions.value = [] //
try {
//
const params = {
impUnitName: queryParams.value.impUnitName, //
departName: queryParams.value.departName, //
proName: queryParams.value.proName,
}
const res = await getProListByDepartApi(params)
proOptions.value = res.data.map(item => ({
text: item.proName, //
value: item.proName
}))
} catch (e) {
console.error('获取工程下拉失败:', e)
}
};
const filteredEquipmentCategories = computed(() => {
//
//
return equipmentCategories.value
});
const toggleCategory = (index) => {
equipmentCategories.value[index].expanded = !equipmentCategories.value[index].expanded;
}
// /
const toggleProject= (categoryIndex,projectIndex) => {
equipmentCategories.value[categoryIndex].departNameList[projectIndex].expanded =
!equipmentCategories.value[categoryIndex].departNameList[projectIndex].expanded;
}
//
const showDetail= (engineering) => {
//
console.log('查看详情:', engineering);
//
uni.navigateTo({
url: '/pages/materialsStation/equipmentRecord/equipmentRecordDetails?proName='+ engineering.proName,
})
}
//
const getList = async () => {
const params = {
keyWord: queryParams.value.keyWord,
impUnitName: queryParams.value.impUnitName, //
departName: queryParams.value.departName, //
proName: queryParams.value.proName, //
}
console.log('🚀 ~ getList ~ params:', params)
try {
uni.showLoading({ title: '加载中', mask: true })
let res = null
res = await getBranchListApi(params)
console.log('获取设备列表数据:', res)
if (res.code === 200 && res.data) {
equipmentCategories.value = res.data
console.log("xxxxxxxxxxxxxxx",equipmentCategories.value)
//
if (equipmentCategories.value.length === 1) {
equipmentCategories.value[0].expanded = true
}
uni.hideLoading()
}
} catch (error) {
console.error('获取设备列表失败:', error)
equipmentCategories.value = []
} finally {
uni.hideLoading()
}
}
</script>
<style lang="scss" scoped>
.content {
padding: 10px;
height: calc(100vh - 100px);
//
.addBtn {
height: 60rpx;
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
text-align: center;
line-height: 60rpx;
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
//
.card {
padding: 4rpx;
background-color: #fff;
border-radius: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
margin-bottom: 24rpx;
//
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
.title {
font-size: 12rpx;
font-weight: 600;
color: #262626;
position: relative;
padding-left: 2rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #3784fb;
border-radius: 6rpx;
}
}
.header-right {
.tip {
font-size: 26rpx;
color: #8c8c8c;
}
}
}
//
.uni-group {
display: flex;
justify-content: center;
align-items: center;
.uni-icons {
padding: 8rpx;
border-radius: 8rpx;
transition: all 0.3s ease;
&:active {
transform: scale(0.9);
opacity: 0.8;
}
}
}
//
.select-area {
padding: 24rpx 0;
border-bottom: 2rpx solid #f5f5f5;
}
}
.search-box {
padding: 10px;
background: #fff;
margin-bottom: 10px;
border-radius: 8px;
display: flex;
align-items: center;
}
.equipment-list {
background: #fff;
border-radius: 8px;
overflow: hidden;
.equipment-category-section {
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.equipment-category {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;
font-weight: bold;
padding: 15px;
background: #fafafa;
cursor: pointer;
transition: background-color 0.2s;
&:active {
background: #f0f0f0;
}
.expand-icon {
transition: transform 0.2s;
}
}
.equipment-specs {
.equipment-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 15px;
border-bottom: 1px solid #f5f5f5;
cursor: pointer;
transition: background-color 0.2s;
&:last-child {
border-bottom: none;
}
&:active {
background: #f8f8f8;
}
.equipment-info {
.equipment-name {
color: #333;
font-size: 14px;
}
.equipment-spec {
color: #666;
font-size: 12px;
margin-top: 2px;
}
}
.equipment-quantity {
color: #4aa4ea;
font-size: 14px;
font-weight: 500;
}
}
}
}
/* 二级收缩相关样式 */
.project-section {
margin-left: 10px;
border-left: 2px #f0f0f0;
padding-left: 15px;
}
.project-item {
margin-bottom: 10px;
}
.project-title {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
// background-color: #f8f9fa;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
}
.project-title:active {
background-color: #e9ecef;
}
/* 三级工程列表样式 */
.engineering-list {
margin-top: 8px;
margin-left: 10px;
}
.engineering-item {
padding: 10px 15px;
border: 1px #e9ecef;
border-radius: 4px;
margin-bottom: 8px;
cursor: pointer;
transition: all 0.2s;
}
.engineering-item:hover {
background-color: #f8f9fa;
border-color: #007aff;
}
.engineering-info {
display: flex;
justify-content: space-between;
align-items: center;
}
.engineering-name {
font-weight: 500;
font-size: 14px;
color: #4aa4ea;
}
/* 小图标样式 */
.expand-icon-small {
transition: transform 0.2s;
}
}
}
.count {
color: #007aff;
}
.scroll-container {
height: calc(100vh - 150px);
}
</style>

View File

@ -0,0 +1,390 @@
<template>
<uni-nav-bar dark :fixed="true" shadow background-color="#4AA4EA" status-bar title="台账查询">
<template v-slot:left>
<view style="font-size: 18px; display: flex; align-items: center" @click="back">
<uni-icons type="left" size="20" color="#fff"></uni-icons>
<text>返回</text>
</view>
</template>
</uni-nav-bar>
<div class="content">
<!-- 搜索区域 -->
<uni-row :gutter="24" class="search-form">
<uni-col :span="18">
<view>
<uni-easyinput v-model="queryParams.typeName" placeholder="物资名称"/>
</view>
</uni-col>
<uni-col :span="18">
<view>
<uni-easyinput v-model="queryParams.typeModelName" placeholder="规格型号"/>
</view>
</uni-col>
<uni-col :span="6">
<view class="search" @click="getDetailsList">查询</view>
</uni-col>
</uni-row>
<!-- <uni-easyinput v-model="searchCode" placeholder="输入设备编码" class="search-input" /> -->
<!-- <uni-row
:gutter="30"
style="display: flex; align-items: center;margin-top:10px "
>
<uni-col :span="12">
<uni-forms-item name="typeModelName" >
<uni-easyinput
v-model="queryParams.typeModelName"
placeholder="物资名称"
clearable
/>
</uni-forms-item>
</uni-col>
<uni-col :span="12">
<uni-forms-item name="typeName" >
<uni-easyinput
v-model="queryParams.typeName"
placeholder="规格型号"
clearable
/>
</uni-forms-item>
</uni-col>
<uni-col :span="6">
<view class="addBtn" @click="getList">查询</view>
</uni-col>
</uni-row> -->
<!-- 设备列表 -->
<div class="card" style="margin-top: 10px;">
<div style="width: 98%;height: auto;overflow-x: auto;">
<uni-table border stripe emptyText="暂无更多数据" >
<!-- 表头行 -->
<uni-tr>
<uni-th width="100px" align="center" style="font-size: 24rpx;">班组名称</uni-th>
<uni-th width="100px" align="center" style="font-size: 24rpx;">物资名称</uni-th>
<uni-th width="100px" align="center" style="font-size: 24rpx;">规格型号</uni-th>
<uni-th width="40px" align="center" style="font-size: 24rpx;">数量</uni-th>
<uni-th width="80px" align="center" style="font-size: 24rpx;">计量单位</uni-th>
</uni-tr>
<!-- 表格数据行 -->
<uni-tr v-for="item in equipmentList" :key="item.id">
<uni-td style="font-size: 22rpx;" align="center">{{item.teamName}}</uni-td>
<uni-td style="font-size: 22rpx;" align="center">{{item.typeName}}</uni-td>
<uni-td style="font-size: 22rpx;" align="center">{{item.typeModelName}}</uni-td>
<uni-td style="font-size: 22rpx;" align="center">{{item.allNum}}</uni-td>
<uni-td style="font-size: 22rpx;" align="center">{{item.unit}}</uni-td>
</uni-tr>
</uni-table>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getRetainedEquipmentListApi } from '@/services/materialsStation'
const proName = ref('')
const searchCode = ref('')
const selectedStatusIndex = ref(0)
const equipmentList = ref([])
const queryParams = ref({
typeModelName: '',
typeName: '',
})
const back = () => {
uni.navigateBack({
delta: 1,
})
}
onLoad((options) => {
console.log(options)
proName.value = options.proName
getDetailsList()
})
//
const getDetailsList = async () => {
const params = {
proName: proName.value,
typeModelName: queryParams.value.typeModelName,
typeName: queryParams.value.typeName,
isApp:0
}
console.log('yyyyyyyyyyy:', params)
try {
const res = await getRetainedEquipmentListApi(params)
console.log('获取设备详情列表数据:', res)
if (res.code === 200) {
equipmentList.value = res.data
}
} catch (error) {
console.error('获取设备列表失败:', error)
equipmentList.value = []
}
}
</script>
<style lang="scss" scoped>
/* 样式部分保持不变 */
.content {
padding: 10px;
height: calc(100vh - 100px);
//
.search-form {
display: flex;
align-items: center;
background: #fff;
padding: 10rpx;
border-radius: 20rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
.select-box{
width: 100%;
height: 80rpx;
}
.select-box-content{
height: 75rpx;
width: auto;
display: flex;
align-items: center;
flex-wrap: nowrap;
}
.select-box-item{
width: auto;
padding: 5rpx;
margin-right: 10rpx;
height: 60rpx;
line-height: 60rpx;
font-size: 24rpx;
word-break: keep-all;
white-space: nowrap;
}
//
.search {
height: 60rpx;
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
text-align: center;
line-height: 60rpx;
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
}
//
.addBtn {
height: 30rpx;
background: linear-gradient(135deg, #19be6b 0%, #16a75c 100%);
text-align: center;
line-height: 80rpx;
color: #fff;
border-radius: 12rpx;
font-size: 24rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(25, 190, 107, 0.2);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
//
.card {
padding: 4rpx;
background-color: #fff;
border-radius: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
margin-bottom: 24rpx;
//
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
.title {
font-size: 12rpx;
font-weight: 600;
color: #262626;
position: relative;
padding-left: 2rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #3784fb;
border-radius: 6rpx;
}
}
.header-right {
.tip {
font-size: 26rpx;
color: #8c8c8c;
}
}
}
//
.uni-group {
display: flex;
justify-content: center;
align-items: center;
.uni-icons {
padding: 8rpx;
border-radius: 8rpx;
transition: all 0.3s ease;
&:active {
transform: scale(0.9);
opacity: 0.8;
}
}
}
//
.select-area {
padding: 24rpx 0;
border-bottom: 2rpx solid #f5f5f5;
}
}
.search-section {
background: #fff;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
.search-container {
display: flex;
gap: 10px;
align-items: center;
.search-input {
flex: 1;
}
.status-picker {
flex: 1;
.picker-display {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
color: #333;
font-size: 14px;
}
}
}
}
.equipment-list {
.equipment-item {
background: #fff;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: flex-start;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
.equipment-info {
flex: 1;
.equipment-code {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 8px;
}
.equipment-details {
.detail-row {
display: flex;
margin-bottom: 4px;
font-size: 14px;
&:last-child {
margin-bottom: 0;
}
.label {
color: #666;
min-width: 70px;
}
.value {
color: #333;
}
}
}
}
.status-tag {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
&.status-normal {
background: #e8f5e8;
color: #52c41a;
}
&.status-warning-3 {
background: #fff7e6;
color: #fa8c16;
}
&.status-warning-1 {
background: #fff2f0;
color: #ff4d4f;
}
&.status-expired {
background: #fff2f0;
color: #ff4d4f;
}
}
}
}
}
.scroll-container {
height: calc(100vh - 200px);
}
</style>

View File

@ -78,6 +78,7 @@ const isUsingList = ref([
{ path: 'teamWarning', name: '班组预警', src: 'teamWarning', isShow: true },
{ path: 'authorizeSignature', name: '项目部授权', src: 'authorizeSignature', isShow: true },
{ path: 'materialClerkConfirms', name: '领料确认', src: 'outStore', isShow: true },
{ path: 'equipmentRecord', name: '站内库存台账', src: 'ledger', isShow: true },
])
const userAgent = navigator.userAgent.toLowerCase()

View File

@ -256,6 +256,51 @@ export const getToolsDetailsListApi = (data) => {
})
}
// 站内库存台账-列表
export const getBranchListApi = (data) => {
return http({
method: 'GET',
url: '/material/material_maMachine/getBranchList',
data,
})
}
// 站内库存台账-详情
export const getRetainedEquipmentListApi = (data) => {
return http({
method: 'GET',
url: '/material/material_maMachine/getRetainedEquipmentList',
data,
})
}
//分公司下拉
export const getImpUnitListApi= (data) => {
return http({
url: '/material/material_maMachine/getImpUnitNameList',
method: 'GET',
data
})
}
//项目部下拉
export const getDepartListByImpUnitApi= (data) => {
return http({
url: '/material/material_maMachine/getDepartNameList',
method: 'GET',
data
})
}
//工程下拉
export const getProListByDepartApi= (data) => {
return http({
url: '/material/material_maMachine/getProjectList',
method: 'GET',
data
})
}
// 班组库存
export const getTeamUseNumList = (data) => {
return http({