Files
entityControl_mobile/pages/storage/index.vue
2026-03-06 16:50:46 +08:00

558 lines
14 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="container">
<!-- 头部 -->
<!-- <view class="header">
<text class="title">仓库管理系统</text>
<view class="user">admin</view>
</view> -->
<!-- 仓库概览 -->
<view class="section">
<view class="section-title">仓库概览</view>
<view class="stats-container" style="flex-wrap: wrap;">
<view v-for="item in warehouseData" :key="item.cangkuCode" class="stats-container" @tap="warehouseTap(item)" style="flex-direction: column;margin: 10rpx;background-color: #f8f9fa;width: 40%;padding: 20rpx;">
<view style="margin-left: 10rpx;font-size: 28rpx;">{{ item.cangkuName }}</view>
<view class="stats-container">
<view class="stat-box">
<text class="label">总览</text>
<text class="number">{{ item.totalSlot }}</text>
</view>
<view class="stat-box">
<text class="label">可用</text>
<text class="number">{{ item.unusedSlot }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 主要功能 -->
<view class="section">
<view class="section-title">主要功能</view>
<view class="function-container">
<view class="function-btn" v-for="(item, index) in mainFunctions" :key="index" @tap="handleFunction(item.type)" style="position: relative;">
<image :src="item.icon" mode="scaleToFill" />
<uv-badge type="error" max="100" :value="taskNum" absolute :offset="['15%','43%']" v-show="item.type == 'inventory'"></uv-badge>
<text class="label">{{ item.label }}</text>
</view>
</view>
</view>
<view class="section">
<view class="section-title">预警信息</view>
<view >
<canvas canvas-id="inventoryAgeEchatrs" id="inventoryAgeEchatrs" class="warningEchatrs" @touchend="tap"/>
</view>
</view>
<view class="section">
<view class="section-title" style="display: flex;align-items: center;">
<view>月入库统计</view>
<!-- <uni-data-select
v-model="inventoryParams.range"
:localdata="inventoryData"
@change="change"
:clear="false"
></uni-data-select> -->
</view>
<view >
<view class="stats-container">
<view class="stat-box" style="width: 48%;padding: 30rpx 0;">
<text class="label">项目数</text>
<text class="number">{{ chartDataInventory.monthInCount }}</text>
</view>
<view class="stat-box" style="width: 48%;padding: 30rpx 0;">
<text class="label">条目数</text>
<text class="number">{{ chartDataInventory.monthInProjectCount }}</text>
</view>
</view>
<view class="stats-container">
<view class="stat-box" style="width: 100%;padding: 30rpx 0;">
<text class="label">总金额</text>
<text class="number">{{ chartDataInventory.monthInAmount }}</text>
</view>
</view>
<!-- <qiun-data-charts
type="line"
:opts="optsInventory"
:chartData="chartDataInventory"
:ontouch="true"
/> -->
</view>
<view class="section-title">月出库统计</view>
<view >
<view class="stats-container">
<view class="stat-box" style="width: 48%;padding: 30rpx 0;">
<text class="label">项目数</text>
<text class="number">{{ chartDataInventory.monthOutCount }}</text>
</view>
<view class="stat-box" style="width: 48%;padding: 30rpx 0;">
<text class="label">条目数</text>
<text class="number">{{ chartDataInventory.monthOutProjectCount }}</text>
</view>
</view>
<view class="stats-container">
<view class="stat-box" style="width: 100%;padding: 30rpx 0;">
<text class="label">总金额</text>
<text class="number">{{ chartDataInventory.monthOutAmount }}</text>
</view>
</view>
<!-- <qiun-data-charts
type="line"
:opts="optsInventory"
:chartData="chartDataOutInventory"
:ontouch="true"
/> -->
</view>
</view>
<uv-modal ref="warehouseModalRef" :title="warehouseObj.title + '可用库位'" class="warehouseModalForm">
<view class="slot-content" style="width: 100%;height: 500rpx;overflow: auto;">
<view class="list-item" v-for="(item, index) in warehouseObj.list" :key="index">
<view class="item-name">位置{{ item.pcode }}</view>
</view>
</view>
</uv-modal>
<!-- 库存管理 -->
<!-- <view class="section">
<view class="section-title">库存管理</view>
<view class="function-container">
<view class="function-btn" v-for="(item, index) in inventoryFunctions" :key="index" @tap="handleInventory(item.type)">
<text class="icon">{{ item.icon }}</text>
<text class="label">{{ item.label }}</text>
</view>
</view>
</view> -->
<!-- 统计分析 -->
<!-- <view class="section">
<view class="section-title">统计分析</view>
<view class="stat-row">
<text>出入库统计入库{{ statistics.inbound }} 出库{{ statistics.outbound }}</text>
</view>
<view class="stat-row">
<text>月度库存趋势总库存{{ statistics.total }} 库位使用率{{ statistics.usage }}%</text>
</view>
</view> -->
</view>
</template>
<script setup>
import { ref, reactive } from 'vue'
import inQuerySvg from '../../static/iconfont/inQuery.svg'
import outQuerySvg from '../../static/iconfont/outQuery.svg'
import inventorySvg from '../../static/iconfont/inventory.svg'
import dispatchSvg from '../../static/iconfont/dispatch.svg'
import { taskCount } from '../../api/inventory'
import { getInventoryReview, getWarehouseAvailable, getInventoryAge, getInventory } from '../../api/storage'
import { onReady, onShow } from '@dcloudio/uni-app'
import uCharts from '@/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js'
var uChartsInstance = {};
// 主要功能列表
const mainFunctions = reactive([
{ type: 'inbound', icon: inQuerySvg, label: '入库' },
{ type: 'outbound', icon: outQuerySvg, label: '出库' },
{ type: 'inventory', icon: inventorySvg, label: '盘点' },
{ type: 'dispatch', icon: dispatchSvg, label: '智能调度' }
])
// 处理主要功能点击
const handleFunction = (type) => {
// 处理各功能的点击事件
if (type == 'inbound') {
console.log("跳转")
uni.navigateTo({
url: '/pagesStorage/inStorage',
})
} else if (type == 'outbound') {
console.log("跳转")
uni.navigateTo({
url: '/pagesStorage/outStorage',
})
} else if (type == 'inventory') {
console.log("跳转")
uni.navigateTo({
url: '/pagesInventory/inventoryTask',
})
}else if(type == 'dispatch'){
uni.navigateTo({
url: '/pagesDispatch/dispatchList',
})
}
console.log('功能点击:', type)
}
// 仓库概览数据
const warehouseData = ref([])
const getInventoryReviewList = () => {
getInventoryReview().then(res => {
warehouseData.value = res.data
})
}
const taskNum = ref(0)
const getTaskCount = () => {
taskCount().then(res => {
taskNum.value = res.data
})
}
const getInventoryAgeList = () => {
getInventoryAge().then(res => {
getServerData(res.data)
})
}
const inventoryData = ref([
{ value: 0, text: "最近一周" },
{ value: 2, text: "最近半年" },
])
const inventoryParams = ref({
range: 0
})
const change = (e) => {
console.log("e:", inventoryParams.value);
getInventoryList()
}
const getInventoryList = () => {
let data = inventoryParams.value
getInventory(data).then(res => {
chartDataInventory.value = res.data.kpi
console.log("res:", res);
// getDataInventory(res.data)
})
}
const getServerData = (data) => {
let res = {
series: [
{
data: data
}
]
};
drawCharts('inventoryAgeEchatrs', res);
}
const cWidth = ref(610)
const cHeight = ref(500)
const drawCharts = (id,data) => {
const ctx = uni.createCanvasContext(id, this);
uChartsInstance[id] = new uCharts({
type: "pie",
context: ctx,
width: cWidth.value,
height: cHeight.value,
series: data.series,
animation: true,
background: "#FFFFFF",
color: ["#1890FF","#91CB74","#FAC858","#EE6666","#73C0DE","#3CA272","#FC8452","#9A60B4","#ea7ccc"],
float:"center",
position:"left",
enableScroll: false,
extra: {
pie: {
activeOpacity: 0.5,
activeRadius: 10,
offsetAngle: 0,
labelWidth: 15,
border: false,
borderWidth: 3,
borderColor: "#FFFFFF"
}
}
});
}
const tap = (e) => {
uChartsInstance[e.target.id].touchLegend(e);
uChartsInstance[e.target.id].showToolTip(e);
}
const chartDataInventory = ref ({})
const chartDataOutInventory = ref ({})
const optsInventory = ref ({
color: ["#1890FF","#91CB74","#FAC858","#EE6666","#73C0DE","#3CA272","#FC8452","#9A60B4","#ea7ccc"],
padding: [15,10,0,15],
enableScroll: true,
legend: {},
xAxis: {
disableGrid: true,
scrollShow: true,
itemCount: 4
},
yAxis: {
gridType: "dash",
dashLength: 2
},
extra: {
line: {
type: "straight",
width: 2,
activeType: "hollow"
}
}
})
const getDataInventory = (data) => {
let xData = []
let inProjectData = []
let inItemData = []
data.forEach(e => {
xData.push(e.bucket)
inProjectData.push(e.inProjectCount)
inItemData.push(e.inItemCount)
});
let inRes = {
categories: xData,
series: [
{
name: "项目数",
data: inProjectData
},
{
name: "条目数",
data: inItemData
}
]
};
chartDataInventory.value = JSON.parse(JSON.stringify(inRes));
let outProjectData = []
let outItemData = []
data.forEach(e => {
outProjectData.push(e.outProjectCount)
outItemData.push(e.outItemCount)
});
let outRes = {
categories: xData,
series: [
{
name: "项目数",
data: outProjectData
},
{
name: "条目数",
data: outItemData
}
]
};
chartDataOutInventory.value = JSON.parse(JSON.stringify(outRes));
}
const warehouseObj = ref({
title: "可用库位",
list: []
})
const warehouseModalRef = ref(null)
const warehouseTap = (item) => {
console.log("item:", item);
warehouseObj.value.title = item.warehouseName
// getWarehouseAvailable({warehouseCode: item.warehouseCode}).then(res => {
// console.log("res:", res);
// warehouseObj.value.list = res.data[0].positions
// })
// warehouseModalRef.value.open()
}
const warehouseSubmit = () => {
warehouseModalRef.value.show()
}
onReady(() => {
})
onShow(() => {
if (uni.getStorageSync('token')) {
getInventoryReviewList()
getTaskCount()
getInventoryAgeList()
getInventoryList()
}
cWidth.value = uni.upx2px(610);
cHeight.value = uni.upx2px(500);
})
// 库存管理功能
const inventoryFunctions = reactive([
{ type: 'search', icon: '🔍', label: '库位查询' },
{ type: 'stats', icon: '📊', label: '库存统计' }
])
// 处理库存管理功能点击
const handleInventory = (type) => {
console.log('库存管理点击:', type)
}
// 统计数据
const statistics = reactive({
inbound: 156,
outbound: 89,
total: 1234,
usage: 74
})
</script>
<style scoped lang="scss">
.container {
padding: 30rpx;
background-color: #f7f7f7;
padding-bottom: env(safe-area-inset-bottom);
}
.header {
background-color: #fff;
padding: 30rpx;
margin-bottom: 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 20rpx;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
}
.header .title {
font-size: 36rpx;
font-weight: 600;
}
.header .user {
display: flex;
align-items: center;
gap: 10rpx;
}
.section {
background: #fff;
padding: 40rpx;
margin-bottom: 30rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
::v-deep .uni-select{
height: 50rpx !important;
width: 240rpx;
margin-left: 20rpx;
}
::v-deep .uni-select__input-box{
height: 50rpx !important;
}
}
.section-title {
font-size: 32rpx;
margin-bottom: 34rpx;
font-weight: 600;
color: #333;
}
.stats-container {
display: flex;
justify-content: space-between;
}
.stat-box {
margin: 10rpx;
background: #f8f9fa;
border-radius: 16rpx;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.stat-box .label {
color: #666;
font-size: 28rpx;
}
.stat-box .number {
font-size: 48rpx;
font-weight: 600;
color: #199793;
}
.function-container {
display: flex;
flex-wrap: wrap;
}
.function-btn {
margin: 16rpx;
flex: 1;
min-width: 30%;
display: flex;
flex-direction: column;
align-items: center;
padding: 40rpx 20rpx;
background: #f8f9fa;
border-radius: 16rpx;
image {
width: 70rpx;
height: 70rpx;
margin-bottom: 10rpx;
}
}
.function-btn .icon {
font-size: 48rpx;
margin-bottom: 16rpx;
}
.function-btn .label {
font-size: 28rpx;
color: #666;
}
.stat-row {
background: #f8f9fa;
padding: 30rpx;
margin: 20rpx 0;
border-radius: 16rpx;
font-size: 28rpx;
color: #666;
}
.warningEchatrs{
width: 610rpx;
height: 500rpx;
}
.warehouseModalForm{
.list-item {
padding: 20rpx 10rpx;
border-bottom: 1rpx solid #eee;
.item-name {
font-size: 32rpx;
color: #3b4144;
font-weight: 400;
}
}
}
</style>