优化
This commit is contained in:
101
pages/inventory/index.vue
Normal file
101
pages/inventory/index.vue
Normal 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
132
pages/login/login.vue
Normal 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
134
pages/mine/index copy.vue
Normal 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
291
pages/mine/index.vue
Normal 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
558
pages/storage/index.vue
Normal 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>
|
||||
Reference in New Issue
Block a user