This commit is contained in:
2026-03-06 16:50:46 +08:00
commit 0704be4c9f
249 changed files with 46365 additions and 0 deletions

101
pages/inventory/index.vue Normal file
View File

@@ -0,0 +1,101 @@
<template>
<view class="iconBox">
<view class="iconItem">
<view @tap="goDevice">
<view class="icon">
<image src="../../static/iconfont/boundDevice.svg" mode="scaleToFill" />
</view>
<view class="text">设备绑定</view>
</view>
</view>
<view class="iconItem">
<view @tap="goInventory">
<view class="icon">
<image src="../../static/iconfont/inventory.svg" mode="scaleToFill" />
</view>
<view class="text">仓库盘点</view>
</view>
</view>
<view class="iconItem">
<view @tap="goHistory">
<view class="icon">
<image src="../../static/iconfont/history.svg" mode="scaleToFill" />
</view>
<view class="text">盘点清单</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
onLoad(() => {
})
const goDevice = () => {
uni.navigateTo({
url: '/pagesInventory/boundDevice-old',
})
}
const goInventory = () => {
if (uni.getStorageSync("deviceInfo") && Object.keys(uni.getStorageSync("deviceInfo")).length > 0) {
uni.navigateTo({
url: '/pagesInventory/inventory-old',
})
console.log("有数据")
} else {
console.log("无数据")
uni.showToast({
title: '请先去绑定设备',
icon: 'none'
})
}
}
const goHistory = () => {
uni.navigateTo({
url: '/pagesInventory/history',
})
}
</script>
<style scoped lang="scss">
.iconBox {
display: flex;
align-items: center;
flex-wrap: wrap;
.iconItem {
width: 25%;
display: flex;
align-items: center;
justify-items: center;
flex-direction: column;
margin: 20rpx 0;
.icon {
width: 110rpx;
height: 110rpx;
display: flex;
align-items: center;
justify-content: center;
// background: #199793;
// border-radius: 50%;
image {
width: 60rpx;
height: 60rpx;
}
}
.text {
margin-top: 14rpx;
font-size: 28rpx;
}
}
}
</style>

132
pages/login/login.vue Normal file
View File

@@ -0,0 +1,132 @@
<template>
<view class="container">
<view class="huanying">HELLO</view>
<view class="huanyingText">
欢迎登录
<text>实物管控智慧云</text>
</view>
<view class="huanyingDes">
用智慧云管好实物资产
<!-- 实物管控智慧云全掌握 -->
<!-- 智慧云实物管控好帮手 -->
<!-- 智慧云助力实物精管控 -->
</view>
<uv-form labelPosition="left" :model="formModel" labelWidth="80" :rules="rules" class="formContent" ref="formRef">
<uv-form-item label="用户名" prop="userInfo.username" borderBottom>
<uv-input v-model="formModel.userInfo.username" border="none" placeholder="请输入用户名" />
</uv-form-item>
<uv-form-item label="密码" prop="userInfo.password" borderBottom>
<uv-input v-model="formModel.userInfo.password" :type="showPass ? '' : 'password'" border="none" placeholder="请输入密码" />
<template v-slot:right>
<uv-icon name="eye" @tap="changePassStatus" v-show="!showPass"></uv-icon>
<uv-icon name="eye-off-outline" @tap="changePassStatus" v-show="showPass"></uv-icon>
</template>
</uv-form-item>
<uv-button type="primary" size="large" text="登 录" shape="circle" color="#199793" customStyle="margin-top: 50px" @click="submit"></uv-button>
</uv-form>
</view>
</template>
<script setup>
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { userLogin } from "@/api/login"
const formModel = ref({
userInfo: {
username: '',
password: '',
},
})
const showPass = ref(false)
const formRef = ref()
const rules = ({
'userInfo.username': {
type: 'string',
required: true,
message: '输入用户名',
trigger: ['blur', 'change']
},
'userInfo.password': {
type: 'string',
required: true,
message: '请填写密码',
trigger: ['blur', 'change']
},
})
const changePassStatus = () => {
showPass.value = !showPass.value
}
// 提交
const submit = () => {
// 如果有错误会在catch中返回报错信息数组校验通过则在then中返回true
formRef.value.validate().then(res => {
userLogin(formModel.value.userInfo).then(res => {
console.log("登录成功", res)
uni.setStorageSync('token', res.data.token)
uni.setStorageSync('user', res.data.user)
uni.switchTab({
url: "/pages/storage/index"
})
})
}).catch(errors => {
// uni.showToast({
// icon: 'error',
// title: '校验失败'
// })
})
}
</script>
<style lang="scss" scoped>
.container{
// display: flex;
// align-items: center;
// justify-content: center;
// flex-direction: column;
padding: 0 56rpx;
.title{
font-size: 72rpx;
}
.formContent{
// width: 80%;
margin-top: 140rpx;
}
.huanyingText {
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 34rpx;
color: #000000;
line-height: 44rpx;
font-style: normal;
margin-top: 38rpx;
text {
color: #199793;
}
}
.huanying {
margin-top: 130rpx;
font-family: PingFang SC, PingFang SC;
font-weight: bold;
font-size: 72rpx;
color: #000000;
}
.huanyingDes {
font-family: PingFang SC, PingFang SC;
font-weight: 400;
font-size: 28rpx;
color: #999999;
line-height: 44rpx;
font-style: normal;
margin-top: 24rpx;
}
}
::v-deep .uv-input__content{
flex-direction: column;
align-items: unset;
}
</style>

134
pages/mine/index copy.vue Normal file
View File

@@ -0,0 +1,134 @@
<template>
<view class="mine-container">
<!--顶部个人信息栏-->
<view class="header-section">
<view class="header-box">
<view class="header-info">
<view v-if="!userName" class="cu-avatar">
<image :src="userAvatar" mode="widthFix"></image>
</view>
<image v-else :src="userAvatar" class="cu-avatar" mode="widthFix"></image>
<view v-if="!userName" class="login-tip">
点击登录
</view>
<view v-else @click="handleToInfo" class="user-info">
<view class="u_title">
用户名{{ userName }}
</view>
</view>
</view>
<view @click="handleToInfo" class="header-info">
<text>个人信息</text>
<uv-icon name="arrow-right" color="#FFFFFF"></uv-icon>
</view>
</view>
</view>
<uv-list>
<uv-list-item title="关于我们" border></uv-list-item>
<uv-list-item title="退出登录" border></uv-list-item>
</uv-list>
</view>
</template>
<script setup>
import { computed, onMounted, ref } from 'vue'
import userAvatar from "@/static/tabbar/mine.png"
// 从store获取用户信息
const userName = ref("")
const handleLogout = () => {
uni.showModal({
title: '提示',
content: '确定注销并退出系统吗?',
success: (res) => {
if (res.confirm) {
store.dispatch('LogOut').then(() => {
uni.reLaunch({ url: '/pages/index' })
})
}
}
})
}
</script>
<style scoped lang="scss">
page {
background-color: #f5f6f7;
}
.header-section {
padding: 30rpx 30rpx 90px 30rpx;
background-color: #199793;
color: white;
.header-box {
padding: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
.header-info {
display: flex;
align-items: center;
}
}
.login-tip {
font-size: 18px;
margin-left: 10px;
}
.cu-avatar {
width: 128rpx;
height: 128rpx;
border-radius: 50%;
background-color: #FFFFFF;
image {
width: 98rpx;
height: 98rpx;
margin: 15rpx;
}
}
.user-info {
margin-left: 15px;
.u_title {
font-size: 18px;
line-height: 30px;
}
}
}
.content-section {
position: relative;
top: -50px;
.mine-actions {
margin: 15px 15px;
padding: 20px 0px;
border-radius: 8px;
background-color: white;
.action-item {
.icon {
font-size: 28px;
}
.text {
display: block;
font-size: 13px;
margin: 8px 0px;
}
}
}
}
</style>

291
pages/mine/index.vue Normal file
View File

@@ -0,0 +1,291 @@
<template>
<view class="container">
<!-- 头部个人信息 -->
<view class="header">
<view class="avatar-container" @tap="goLogin">
<view class="avatar">
<image
src="../../static/image/user.png"
mode="scaleToFill"
/>
</view>
</view>
<view class="user-info" @tap="goLogin">
<text class="username">{{ userInfo.username }}</text>
<text class="user-role">{{ userInfo.role }}</text>
</view>
</view>
<!-- 统计信息栏 -->
<!-- <view class="stats-bar">
<view class="stat-item" v-for="(item, index) in statsData" :key="index">
<text class="stat-number">{{ item.number }}</text>
<text class="stat-label">{{ item.label }}</text>
</view>
</view> -->
<!-- 菜单区域 -->
<view class="menu-section">
<!-- 账户信息组 -->
<!-- <view class="menu-group">
<view class="menu-item" v-for="(item, index) in accountMenus" :key="index" @tap="handleMenu(item)">
<text class="menu-icon">{{ item.icon }}</text>
<text class="menu-text">{{ item.text }}</text>
<uv-icon name="arrow-right" color="#999999"></uv-icon>
</view>
</view> -->
<!-- 工作相关组 -->
<view class="menu-group">
<view class="menu-item" v-for="(item, index) in workMenus" :key="index" @tap="handleMenu(item)">
<image :src="item.icon" mode="scaleToFill" />
<text class="menu-text">{{ item.text }}</text>
<!-- absolute :offset="['15%','43%']" -->
<uv-badge type="error" max="100" :value="item.num" v-show="item.num"></uv-badge>
<uv-icon name="arrow-right" color="#999999"></uv-icon>
</view>
</view>
<!-- 系统相关组 -->
<!-- <view class="menu-group">
<view class="menu-item" v-for="(item, index) in systemMenus" :key="index" @tap="handleMenu(item)">
<text class="menu-icon">{{ item.icon }}</text>
<text class="menu-text">{{ item.text }}</text>
<uv-icon name="arrow-right" color="#999999"></uv-icon>
</view>
</view> -->
</view>
<view class="btn" v-show="uni.getStorageSync('token')">
<uv-button text="退 出 登 录" size="large" style="width: 100%;" type="error" @tap="logOut"></uv-button>
</view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { taskCount } from '../../api/inventory'
import { userLogout } from '../../api/login'
import { auditCount } from "@/api/mine"
import { onShow } from '@dcloudio/uni-app'
import myTask from "../../static/iconfont/myTask.svg"
import print from "../../static/iconfont/print.svg"
// 用户信息
const userInfo = reactive({
username: '请登录',
role: ''
})
const goLogin = () => {
uni.reLaunch({
url: '/pages/login/login',
})
}
// 统计数据
const statsData = reactive([
{ number: '128', label: '今日入库' },
{ number: '89', label: '今日出库' },
{ number: '98%', label: '任务完成' }
])
// 工作相关菜单
const workMenus = reactive([
{ icon: myTask, text: '我的任务', type: 'task' },
// { icon: myTask, text: '待审核', type: 'audit' },
{ icon: print, text: '打印调试', type: 'print' },
{ icon: print, text: '签字调试', type: 'signature' }
])
const getCount = () => {
taskCount().then(res => {
workMenus[0].num = res.data
})
// let obj = {
// approverId: uni.getStorageSync('user').userId
// }
// auditCount(obj).then(res => {
// // console.log('审核数量', res.data)
// workMenus[1].num = res.data
// })
}
onShow(() => {
if (uni.getStorageSync('token')) {
userInfo.username = uni.getStorageSync('user').userName
userInfo.role = uni.getStorageSync('user').roles[0].roleName
getCount()
}
})
// 处理菜单点击
const handleMenu = (item) => {
console.log('菜单点击:', item.type)
// 根据类型处理不同的跳转逻辑
if (item.type == "task") {
uni.navigateTo({
url: `/pagesInventory/inventoryTask?type=all`
})
} else if (item.type == "audit") {
uni.navigateTo({
url: `/pagesMine/audit`
})
} else if (item.type == "print") {
uni.navigateTo({
url: `/pagesMine/print`
})
} else if (item.type == "signature") {
uni.navigateTo({
url: `/pagesMine/signPreview`
})
}
}
const logOut = () => {
userLogout().then(res => {
uni.clearStorage()
uni.navigateTo({
url: `/pages/login/login`
})
})
}
</script>
<style scoped lang="scss">
.container {
min-height: 100vh;
background-color: #f7f7f7;
position: relative;
}
.header {
background: linear-gradient(135deg, #199793, #07807b);
padding: 60rpx 40rpx;
color: #ffffff;
text-align: center;
}
.avatar-container {
margin-bottom: 30rpx;
}
.avatar {
width: 160rpx;
height: 160rpx;
border-radius: 50%;
background: #ffffff;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.2);
image {
width: 100rpx;
height: 100rpx;
}
}
.user-info {
margin-top: 20rpx;
}
.username {
font-size: 40rpx;
font-weight: 600;
margin-bottom: 10rpx;
display: block;
}
.user-role {
font-size: 28rpx;
opacity: 0.9;
display: block;
}
.stats-bar {
background: #ffffff;
padding: 30rpx;
display: flex;
justify-content: space-around;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.stat-item {
text-align: center;
}
.stat-number {
font-size: 36rpx;
font-weight: 600;
color: #199793;
display: block;
}
.stat-label {
font-size: 24rpx;
color: #666666;
margin-top: 10rpx;
display: block;
}
.menu-section {
padding: 30rpx 30rpx 100rpx;
}
.menu-group {
background: #ffffff;
border-radius: 20rpx;
margin-bottom: 30rpx;
overflow: hidden;
}
.menu-item {
display: flex;
align-items: center;
padding: 30rpx;
border-bottom: 2rpx solid #f0f0f0;
image {
width: 34rpx;
height: 34rpx;
margin-right: 10rpx;
}
}
.menu-item:last-child {
border-bottom: none;
}
.menu-icon {
width: 48rpx;
height: 48rpx;
margin-right: 30rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
}
.menu-text {
flex: 1;
font-size: 30rpx;
}
.menu-arrow {
color: #999999;
font-size: 28rpx;
}
.btn {
position: absolute;
bottom: 0;
padding: 0 30rpx;
width: 100%;
box-sizing: border-box;
}
</style>

558
pages/storage/index.vue Normal file
View File

@@ -0,0 +1,558 @@
<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>