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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,491 @@
<template>
<view class="container">
<!-- 项目描述,物料号,物料描述,供应商编码,供应商名称,SAP订单编号,入库单据号,出库单据号入库类型库位码 -->
<uv-search v-model="searchValue" placeholder="请输入" searchIcon="scan" :showAction="true" actionText="搜索"
@search="searchList" @custom="searchList" @clickIcon="getScanCode()" style="margin-bottom: 20rpx;"></uv-search>
<view class="section" v-if="list.length">
<view class="section-title">货物信息{{ list.length }}</view>
<view class="info-box" v-for="(item, index) in list" :key="index">
<view
style="display: flex;align-items: center;justify-content: space-between;width: 100%;margin-bottom: 16rpx;">
<!-- <view style="font-weight: bold;">总数量: {{ item.htQty }}</view> -->
<view></view>
<uv-button type="error" v-show="item.outboundStatus" text="已预出库" plain size="mini"></uv-button>
</view>
<view class="info-row">
<text class="info-label">物料号</text>
<text class="info-value">{{ item.wlNo }}</text>
</view>
<view class="info-row">
<text class="info-label">物料描述</text>
<text class="info-value">{{ item.wlMs }}</text>
</view>
<view class="info-row">
<text class="info-label">存放位置</text>
<text class="info-value">{{ item.pcode }}</text>
</view>
<view class="info-row">
<text class="info-label">订单号</text>
<text class="info-value">{{ item.sapNo }}</text>
</view>
<view class="info-row">
<text class="info-label">项目编号</text>
<text class="info-value">{{ item.xmNo }}</text>
</view>
<view class="info-row">
<text class="info-label">项目名称</text>
<text class="info-value">{{ item.xmMs }}</text>
</view>
<view class="info-row">
<text class="info-label">供应商</text>
<text class="info-value">{{ item.gysMc }}</text>
</view>
<view class="info-row">
<text class="info-label">身份码</text>
<text class="info-value">{{ item.entityId || "-" }}</text>
</view>
<view class="info-row">
<text class="info-label">库存数量</text>
<text class="info-value">{{ item.realQty }}({{ item.dw }})</text>
</view>
<!-- <view>
<text class="info-label">出库数量({{ item.dw }})</text>
<view class="info-row" style="margin-top: 10rpx;">
<uv-input placeholder="出库数量" class="form-control" border="surround" clearable v-model="item.htDj"></uv-input>
</view>
</view> -->
<view>
<text class="info-label">现场照片</text>
<!-- name="3" multiple -->
<uv-upload style="margin-top: 10rpx;" :fileList="item.fileList" :maxCount="1" @afterRead="afterRead($event, item)" :previewFullImage="true" @delete="deletePic($event, item)"></uv-upload>
</view>
<view>
<text class="info-label">备注</text>
<uv-textarea v-model="item.remark" placeholder="备注" style="margin-top: 10rpx;"></uv-textarea>
</view>
<view style="display: flex;width: 100%;align-items: center;justify-content: flex-end;margin-top: 20rpx;">
<uv-button type="primary" style="height: 50rpx" text="预出库" @tap="item.outboundStatus = true"
:disabled="item.outboundStatus"></uv-button>
</view>
</view>
</view>
<uv-modal ref="stockModalRef" :rules="stockRules" title="出库信息" class="stockModalForm" :showCancelButton="true"
:closeOnClickOverlay="false" @confirm="stockSubmit" asyncClose>
<view class="slot-content" style="width: 100%;">
<uv-form labelPosition="left" labelWidth="80" :model="formModel" :rules="stockRules" ref="stockFormRef">
<uv-form-item label="出库类型" prop="operationType" borderBottom>
<uni-data-select v-model="formModel.operationType" :localdata="storageTypeData"
placeholder="请选择出类型"></uni-data-select>
</uv-form-item>
<uv-form-item label="领料人" prop="teamCode" borderBottom>
<uni-data-select v-model="formModel.teamCode" :localdata="constructionData"
placeholder="请选择领料人"></uni-data-select>
</uv-form-item>
<uv-form-item label="理货员" prop="operator" borderBottom>
<uni-data-select v-model="formModel.operator" :localdata="userData" placeholder="请选择理货员"></uni-data-select>
</uv-form-item>
<uv-form-item label="预出库" prop="execStatus" borderBottom>
<uni-data-select v-model="formModel.execStatus" :localdata="execStatusList" placeholder="请选择是否预出库"></uni-data-select>
</uv-form-item>
<uv-form-item label="是否配送" prop="isDelivery" borderBottom>
<uni-data-select v-model="formModel.isDelivery" :localdata="deliveryData" placeholder="请选择配送"></uni-data-select>
</uv-form-item>
<!-- <uv-form-item label="出库时间" prop="lyTime" borderBottom>
<uv-input placeholder="请选择出库时间" border="surround" v-model="formModel.lyTime" class="disabledInput"
@tap="openCalendar" disabled>
<template v-slot:suffix>
<uv-icon name="arrow-right" color="#999" size="14"></uv-icon>
</template>
</uv-input>
</uv-form-item> -->
</uv-form>
</view>
</uv-modal>
<!-- <uv-calendar ref="calendarRef" mode="single" class="calendar" @confirm="confirmCalendar"></uv-calendar> -->
<view class="btn">
<uv-button type="primary" text="确定" size="large" style="width: 48%;" v-if="list.length" @tap="openScan">
</uv-button>
<uv-button type="primary" text="确定" size="large" style="width: 48%;" class="mainBtn" v-if="list.length"
@tap="openInfo"> </uv-button>
</view>
</view>
</template>
<script setup>
import { ref, reactive, computed } from 'vue';
import { outStockList, constructionList, outStorageTypeList, userList, addOutStock } from "@/api/storage"
import { onLoad } from "@dcloudio/uni-app";
import { uploadImg } from "@/api/upload"
const searchValue = ref("")
const getScanCode = () => {
uni.scanCode({
success: function (res) {
// console.log('条码内容:' + res.result);
searchValue.value = res.result
searchList()
}
});
}
const list = ref([])
// 搜索列表
const searchList = () => {
let obj = {
keyword: searchValue.value,
pageNum: 1,
pageSize: 200,
isChuku: 0,
}
outStockList(obj).then(res => {
// console.log("搜索", res)
res.rows.forEach(e => {
e.fileList = []
e.outboundStatus = false
});
list.value = res.rows
})
}
// 出库类型
const storageTypeData = ref([])
const getStoragTypeList = () => {
outStorageTypeList({ pageNum: 1, pageSize: 100 }).then(res => {
// console.log("入库类型", res)
res.rows.forEach(item => {
item.value = item.typeCode
item.text = item.typeName
});
storageTypeData.value = res.rows
})
}
// 施工队
const constructionData = ref([])
const getConstructionList = () => {
constructionList({ pageNum: 1, pageSize: 100 }).then(res => {
console.log("施工队", res)
res.rows.forEach(item => {
item.value = item.teamCode
item.text = item.teamName
});
constructionData.value = res.rows
})
}
// 用户
const userData = ref([])
const deliveryData = ref([
{ value: 1, text: '是' },
{ value: 0, text: '否' },
])
const approverData = ref([])
const getUserList = () => {
userList().then(res => {
// console.log("入库类型", res)
res.data.forEach(item => {
item.value = item.userId
item.text = item.userName
});
userData.value = res.data
})
}
// 上传
const afterRead = (event, item) => {
uploadImg(event.file.url, {}).then(res=>{
item.fileList.push({ url: res.url })
})
}
const deletePic = (event, item) => {
item.fileList.splice(event.index, 1)
}
onLoad(() => {
getConstructionList()
getStoragTypeList()
getUserList()
})
const openScan = () => {
uni.scanCode({
scanType: ['qrCode'],
success: function (res) {
console.log('条码内容:' + res.result);
let scanIndex = list.value.findIndex(e => e.pcode == res.result)
if (scanIndex == -1) {
uni.showToast({
title: '未找到该货物',
icon: 'none',
mask: true
})
return
} else {
if (list.value[scanIndex].outboundStatus) {
uni.showToast({
title: '该货物已预出库',
icon: 'none',
mask: true
})
return
}
list.value[scanIndex].outboundStatus = true
}
}
});
}
let ids = ref([])
const openInfo = () => {
formModel.value.operationType = ""
formModel.value.teamCode = ""
formModel.value.operator = ""
formModel.value.isDelivery = null
// formModel.value.lyTime = ""
ids.value = list.value.filter(item => item.outboundStatus)
console.log("ids", ids.value)
if (ids.value.length > 0) {
// const allFileLists = list.value.filter(item => {
// return item.outboundStatus && item.fileList.length > 0
// })
// if (!allFileLists.length) {
// uni.showToast({
// title: "请上传所有出库的货物图片",
// icon: "none"
// })
// return
// }
stockModalRef.value.open()
} else {
uni.showToast({
title: '请选择出库信息',
icon: 'none',
mask: true
})
}
}
// 弹窗
const execStatusList = ref([
{ value: "0", text: "预出库" },
{ value: "1", text: "已出库" },
]);
const stockModalRef = ref(null)
const stockFormRef = ref()
const formModel = ref({
operationType: '',
teamCode: '',
operator: '',
approverId: '',
execStatus: null,
isDelivery: null,
bizType: 1,
// lyTime: '',
})
const stockRules = ref({
'operationType': {
type: 'string',
required: true,
message: '请选择出库类型',
trigger: ['blur', 'change']
},
'teamCode': {
type: 'string',
required: true,
message: '请选择领料人',
trigger: ['blur', 'change']
},
'operator': {
type: 'number',
required: true,
message: '请选择理货员',
trigger: ['blur', 'change']
},
'execStatus': {
type: 'string',
required: true,
message: '请选择是否预出库',
trigger: ['blur', 'change']
},
'isDelivery': {
type: 'number',
required: true,
message: '请选择是否配送',
trigger: ['blur', 'change']
},
'approverId': {
type: 'number',
required: true,
message: '请选择审核员',
trigger: ['blur', 'change']
},
// 'lyTime': {
// type: 'string',
// required: true,
// message: '请选择出库时间',
// trigger: ['blur', 'change']
// },
})
// const calendarRef = ref(null)
// const openCalendar = () => {
// calendarRef.value.open()
// }
// const confirmCalendar = (res) => {
// formModel.value.lyTime = res[0]
// }
const stockSubmit = () => {
stockFormRef.value.validate().then(res => {
let form = JSON.parse(JSON.stringify(formModel.value))
let obj = {
rkBill: {
...form,
},
}
const arr = JSON.parse(JSON.stringify(list.value))
obj.rkInfoList = arr.filter(item => item.outboundStatus)
obj.rkInfoList.forEach(item => {
item.photoUrl = item.fileList.length ? item.fileList[0].url : ''
});
console.log("obj", obj)
addOutStock(obj).then(res => {
stockModalRef.value.close()
uni.showToast({
title: '出库成功',
icon: 'success',
mask: true
})
uni.navigateBack({})
})
}).catch(errors => {
stockModalRef.value.closeLoading()
})
}
</script>
<style scoped lang="scss">
.container {
padding: 30rpx;
padding-bottom: 120rpx;
background-color: #f7f7f7;
min-height: calc(100vh - 60rpx);
position: relative;
}
.section {
background: #fff;
padding: 40rpx;
margin-bottom: 30rpx;
border-radius: 16rpx;
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1);
.form-control {
flex: 1;
border: 2rpx solid #ddd;
border-radius: 8rpx;
font-size: 28rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 40rpx;
color: #333;
border-left: 8rpx solid #2196F3;
padding-left: 20rpx;
}
.info-box {
background: #f8f9fa;
padding: 30rpx;
border-radius: 8rpx;
margin-bottom: 20rpx;
}
.info-row {
display: flex;
justify-content: space-between;
margin-bottom: 16rpx;
}
.info-label {
color: #666;
width: 200rpx;
flex-shrink: 0;
}
.info-value {
font-weight: 500;
}
}
.btn {
position: fixed;
width: calc(100vw - 60rpx);
bottom: 0;
display: flex;
align-items: center;
justify-content: space-between;
background: #FFFFFF;
}
.stockModalForm {
::v-deep .uni-select {
border-color: #FFFFFF;
border-bottom: unset;
padding: 0;
}
:deep(.uv-popup__content) {
overflow: unset !important;
}
::v-deep .uv-modal {
overflow: unset !important;
}
// ::v-deep .uv-input__content {
// flex-direction: column;
// }
::v-deep .uv-input__content__prefix-icon {
margin: 0 !important;
}
::v-deep .uv-input {
padding: 0 !important;
border: unset;
border-color: unset;
height: 70rpx;
}
::v-deep .uni-select__input-placeholder {
font-size: unset;
color: #c0c4cc;
}
::v-deep .uni-select__selector-item {
text-align: left;
}
}
::v-deep uni-toast {
z-index: 30000 !important;
}
::v-deep .calendar {
z-index: 30000 !important;
}
</style>

View File

@@ -0,0 +1,369 @@
<template>
<view class="container">
<z-paging ref="pagingRef" class="containerBox" v-model="listData" :default-page-size="queryParams.pageSize" @query="queryList">
<template #top>
<!-- 项目号/项目描述/物料号/物料描述/供应商编码/供应商名称/订单编号 -->
<uv-search v-model="queryParams.keyword" placeholder="请输入" :showAction="true" actionText="搜索" @search="searchList" @custom="searchList"></uv-search>
<view class="dropDown">
<view class="item_dropDown" @tap="openPicker">
<uv-text :lines="1" :text="storageTypeText" :color="storageTypeText != '全部' ? '#3c9cff': ''" class="item_text"></uv-text>
<uv-icon name="arrow-down-fill" :color="storageTypeText != '全部' ? '#3c9cff': '#666'"></uv-icon>
</view>
</view>
</template>
<view class="box">
<view v-for="item in listData" class="item">
<view class="title">单据号{{ item.billNo }}<uv-icon name="file-text" size="36rpx" style="margin-top: 4rpx;" @tap="itemCopy(item)"></uv-icon></view>
<view><text>入库类型</text>{{ item.rkTypeName }}</view>
<view><text>所属仓库</text>{{ item.cangkuName }}</view>
<view><text>物资类型</text>{{ item.wlTypeName }}</view>
<view><text>理货员</text>{{ item.lihuoY }}</view>
<view><text>入库时间</text>{{ item.createTime }}</view>
<view v-show="item.showMore">
<view><text>订单号</text>{{ item.sapNo }}</view>
<view><text>物料号</text>{{ item.wlNo }}</view>
<view><text>物料描述</text>{{ item.wlMs }}</view>
<view><text>数量</text>{{ item.realQty }}{{ item.dw }}</view>
<view><text>项目定义号</text>{{ item.xmNo }}</view>
<view><text>项目描述</text>{{ item.xmMs }}</view>
<view><text>供应商</text>{{ item.gysMc }}</view>
<view><text>存放位置</text>{{ item.pcode || "-" }}</view>
<view><text>身份码</text>{{ item.entityId || "-" }}</view>
<view><text>备注</text>{{ item.remark || "-" }}</view>
</view>
<view class="more" v-show="!item.showMore" @tap="changeMore(item)">
<view>详细信息</view>
<uv-icon name="arrow-down" color="#A4A6A7" size="28rpx" style="margin-left: 10rpx;"></uv-icon>
</view>
<view class="more" v-show="item.showMore" @tap="changeMore(item)">
<view>收起</view>
<uv-icon name="arrow-up" color="#A4A6A7" size="28rpx" style="margin-left: 10rpx;"></uv-icon>
</view>
</view>
</view>
<view class="btn">
<uv-button type="error" text="确定" size="large" style="width: 48%;" @tap="openModal"> </uv-button>
<uv-button type="primary" text="确定" size="large" class="mainBtn" style="width: 48%;" @tap="goAddInStorage"> </uv-button>
</view>
</z-paging>
<uv-picker ref="picker" :columns="storageType" :keyName="'typeName'" activeColor="#3c9cff" @confirm="pickerConfirm"></uv-picker>
<uv-modal ref="storageModalRef" title="单据号" @confirm="romoveStorage" :showCancelButton="true" :closeOnClickOverlay="false" asyncClose>
<view class="slot-content" style="width: 100%;">
<uv-form labelPosition="left" :model="storageForm" labelWidth="80" :rules="storageRules" ref="storageFormRef">
<uv-form-item label="单据号" prop="billNo" borderBottom>
<uv-input v-model="storageForm.billNo" border="none" placeholder="请输入单据号" />
</uv-form-item>
</uv-form>
</view>
</uv-modal>
</view>
</template>
<script setup>
import { ref, computed } from "vue";
import { onLoad, onShow, onPageScroll } from "@dcloudio/uni-app";
import { storageTypeList, inStockList, deleteStock } from "@/api/storage"
// *****下拉筛选
// 默认值
// const defaultValue = ref([]);
// // 选择结果
// const result = ref([{ name: 'storageType', label: '全部', value: '' }]);
// const activeName = ref('');
// // 筛选条件配置
// const storageType = ref({
// label: '文档格式',
// value: '',
// activeIndex: 0,
// color: '#333',
// activeColor: '#2878ff',
// child: []
// });
// // 计算属性
// const dropItem = computed(() => {
// return (name) => {
// const resultObj = {};
// const find = result.value.find(item => item.name === name);
// if (find) {
// resultObj.label = find.label;
// resultObj.value = find.value;
// } else {
// resultObj.label = getPropertyByName(name).label;
// resultObj.value = getPropertyByName(name).value;
// }
// return resultObj;
// }
// });
// const currentDropItem = computed(() => {
// return getPropertyByName(activeName.value);
// });
// // 工具函数:根据名称获取对应的响应式对象
// function getPropertyByName(name) {
// switch (name) {
// case 'storageType': return storageType.value;
// default: return {};
// }
// }
// // 生命周期钩子
// onPageScroll(() => {
// // 滚动后及时更新位置
// dropDown.value?.init();
// });
// const selectMenu = (e) => {
// const { name, active, type } = e;
// activeName.value = name;
// // type 等于1 的需要特殊处理type不等于1可以忽略
// if (type == 1) {
// clickItem({
// name: 'vip_type',
// label: 'VIP文档',
// value: e.active ? 1 : 0
// });
// } else {
// const find = result.value.find(item => item.name == activeName.value);
// if (find) {
// const findIndex = getPropertyByName(activeName.value).child.findIndex(item =>
// item.label == find.label && item.value == find.value
// );
// getPropertyByName(activeName.value).activeIndex = findIndex;
// } else {
// getPropertyByName(activeName.value).activeIndex = 0;
// }
// }
// };
// const clickItem = (e) => {
// // 下面有重新赋值所以用let
// let { label, value } = e;
// const findIndex = result.value.findIndex(item => item.name == activeName.value);
// if (defaultValue.value.indexOf(value) > -1 && getPropertyByName(activeName.value).label) {
// label = getPropertyByName(activeName.value).label;
// }
// // 已经存在筛选项
// if (findIndex > -1) {
// result.value[findIndex] = {
// name: activeName.value,
// label,
// value
// }
// } else {
// result.value.push({
// name: activeName.value,
// label,
// value
// });
// }
// result.value = result.value.filter(item => defaultValue.value.indexOf(item.value) == -1);
// result.value.forEach(item=> {
// queryParams.value[item.name] = item.value
// })
// pagingRef.value.reload()
// console.log("筛选的值:", queryParams.value)
// };
// const change = (e) => {
// console.log('弹窗打开状态:', e);
// }
const storageType = ref([])
const storageTypeText = ref("全部")
// 获取下拉的列表
const getStoragTypeList = () => {
storageTypeList().then(res =>{
// res.data.forEach(item => {
// item.value = item.typeCode
// item.label = item.typeName
// });
res.data.unshift({typeName: "全部", typeCode: ""})
// console.log("入库类型", res.data)
storageType.value[0] = res.data
})
}
const picker = ref(null)
const openPicker = () => {
picker.value.open()
}
const pickerConfirm = (e) => {
console.log(e)
queryParams.value.rkType = e.value[0].typeCode
storageTypeText.value = e.value[0].typeName
pagingRef.value.reload()
}
const queryParams = ref({
keyword: "",
rkType: "",
pageNum: 1,
pageSize: 10
})
const pagingRef = ref(null)
const listData = ref([])
// 获取列表
const queryList = (pageNo, pageSize) => {
queryParams.value.pageNum = pageNo
console.log(pageNo, pageSize)
inStockList(queryParams.value).then(res => {
res.rows.forEach(e => {
e.showMore = false
})
pagingRef.value.complete(res.rows)
}).catch(res => {
pagingRef.value.complete(false)
})
}
const searchList = () => {
pagingRef.value.reload()
}
onLoad(() => {
getStoragTypeList()
})
onShow(() => {
pagingRef.value?.reload()
})
// 复制
const itemCopy = (item) => {
uni.setClipboardData({
data: item.billNo,
success: function () {
// console.log('success');
}
});
}
// 切换展开收起
const changeMore = (item) => {
item.showMore = !item.showMore
}
const storageModalRef = ref(null)
const storageFormRef = ref(null)
const openModal = () => {
storageModalRef.value.open();
}
const storageForm = ref({
billNo: '',
})
const storageRules = ref({
'billNo': {
type: 'string',
required: true,
message: '请填写单据号',
trigger: ['blur', 'change']
},
})
const romoveStorage = () => {
storageFormRef.value.validate().then(res => {
deleteStock(storageForm.value.billNo).then(res => {
uni.showToast({
title: res.msg,
icon: 'none',
mask: true
})
pagingRef.value.reload()
storageModalRef.value.close()
})
}).catch(errors => {
storageModalRef.value.closeLoading()
})
}
const goAddInStorage = () => {
uni.navigateTo({
url: "/pagesStorage/addInStorage",
})
}
</script>
<style scoped lang="scss">
.container {
position: relative;
.containerBox{
padding: 32rpx;
padding-bottom: 120rpx;
.dropDown{
padding: 0 30rpx;
border-bottom: 1px solid #dadbde;
.item_dropDown{
padding: 20rpx;
display: flex;
align-items: center;
::v-deep .uv-text{
width: unset !important;
flex: unset !important;
}
::v-deep .item_text{
max-width: 200rpx;
margin-right: 10rpx !important;
}
}
}
::v-deep .uv-search {
flex: unset;
}
.box{
// background-color: #ebebeb;
// background-color: #f5f5f5;
// padding-top: 20rpx;
.item {
background: #efefef;
padding: 20rpx;
margin-top: 20rpx;
line-height: 50rpx;
font-size: 28rpx;
border-radius: 8rpx;
color: #333;
.title {
font-size: 32rpx;
font-weight: bold;
display: flex;
align-items: center;
}
text{
color: #666;
}
.more {
color: #A4A6A7;
display: flex;
align-items: center;
}
}
}
.btn{
position: fixed;
width: calc(100vw - 64rpx);
bottom: 0;
left: 32rpx;
z-index: 99;
display: flex;
align-items: center;
justify-content: space-between;
}
}
::v-deep .uv-input__content{
flex-direction: column;
align-items: flex-start;
}
}
</style>

View File

@@ -0,0 +1,84 @@
<template>
<storageList v-model:listData="listData" :storageType="storageType" :storageStatus="storageStatus" pickerCode="rkType"
:queryByParams="queryByParams()" @remove="romoveStorage" @add="goAddInStorage" @reload="handleReload"
:deleteText="'撤 销 入 库'" :GoText="'新 增 入 库'" />
</template>
<script setup>
import { onLoad, onShow } from '@dcloudio/uni-app';
import { ref } from 'vue';
// deleteStock
import { storageTypeList, stockList } from '@/api/storage';
import storageList from './storageList.vue';
const listData = ref([]);
const storageType = ref([]);
let queryParams = ref({
billNo: "",
operationType: "",
pageNum: 1,
pageSize: 10,
bizTypeList: [0]
});
let storageStatus = ref([
[
{ value: "", label: "全部" },
{ value: "0", label: "预入库" },
{ value: "1", label: "已入库" },
]
]);
let queryByParams = () => {
let obj = JSON.parse(JSON.stringify(queryParams.value))
delete obj.rkType
return obj
}
// 获取入库类型列表
const getStoragTypeList = () => {
storageTypeList().then(res => {
res.data.unshift({ typeName: "全部", typeCode: "" });
storageType.value[0] = res.data;
});
};
// 获取列表数据
const handleReload = (params) => {
stockList(params).then(res => {
res.rows.forEach(e => {
e.showMore = false;
});
listData.value = res.rows;
});
};
// 撤销入库
const romoveStorage = (billNo) => {
deleteStock(billNo).then(res => {
uni.showToast({
title: res.msg,
icon: 'none',
mask: true
});
// 重新加载列表
handleReload(queryParams.value);
});
};
// 新增入库
const goAddInStorage = () => {
uni.navigateTo({
url: "/pagesStorage/addInStorage",
});
};
onLoad(() => {
getStoragTypeList();
});
onShow(() => {
handleReload(queryParams.value);
});
</script>

View File

@@ -0,0 +1,88 @@
<template>
<storageList v-model:listData="listData" :storageType="storageType" :storageStatus="storageStatus" pickerCode="ckType"
:queryByParams="queryByParams()" @remove="romoveStorage" @add="goAddOutStorage" @reload="handleReload"
:deleteText="'撤 销 出 库'" :GoText="'新 增 出 库'" />
</template>
<script setup>
import { onLoad, onShow } from '@dcloudio/uni-app';
import { ref } from 'vue';
// deleteOutStock
import { outStorageTypeList, stockList } from '@/api/storage';
import storageList from './storageList.vue';
const listData = ref([]);
const storageType = ref([]);
let queryParams = ref({
billNo: "",
operationType: "",
pageNum: 1,
pageSize: 10,
bizTypeList: [1, 2, 3],
});
let storageStatus = ref([
[
{ value: "", label: "全部" },
{ value: "0", label: "预入库" },
{ value: "1", label: "已入库" },
]
]);
let queryByParams = () => {
let obj = JSON.parse(JSON.stringify(queryParams.value))
delete obj.ckType
return obj
}
// 获取出库类型列表
const getStoragTypeList = () => {
outStorageTypeList({ pageNum: 1, pageSize: 100 }).then(res => {
res.rows.unshift({ typeName: "全部", typeCode: "" });
storageType.value[0] = res.rows;
});
};
// 获取列表数据
const handleReload = (params) => {
stockList(params).then(res => {
res.rows.forEach(e => {
e.showMore = false;
});
listData.value = res.rows;
});
};
// 撤销入库
const romoveStorage = (billNoCk) => {
const obj = {
billNoCk
}
deleteOutStock(obj).then(res => {
uni.showToast({
title: res.msg,
icon: 'none',
mask: true
});
// 重新加载列表
handleReload(queryParams.value);
});
};
// 新增入库
const goAddOutStorage = () => {
uni.navigateTo({
url: "/pagesStorage/addOutStorage",
});
};
onLoad(() => {
console.log('onLoad');
getStoragTypeList();
});
onShow(() => {
handleReload(queryParams.value);
});
</script>

View File

@@ -0,0 +1,209 @@
<template>
<view class="receipt-detail-container">
<!-- <view class="list-title">单据信息</view> -->
<!-- 单据头部信息卡片 -->
<view class="header-card">
<view class="header-item">
<text class="label">单据号</text>
<text class="value">{{ billForm.billNo }}</text>
</view>
<view class="header-item">
<text class="label">{{ storageType == 'rkType' ? '入库类型' : '出库类型' }}</text>
<text class="value">{{ billForm.operationTypeName }}</text>
</view>
<view class="header-item" v-if="storageType == 'rkType'">
<text class="label">物资类型</text>
<text class="value">{{ billForm.wlTypeName }}</text>
</view>
<view class="header-item">
<text class="label">{{ storageType == 'rkType' ? '入库时间' : '出库时间' }}</text>
<text class="value">{{ billForm.operationTime }}</text>
</view>
<view class="header-item" v-if="storageType == 'ckType'">
<text class="label">施工队</text>
<text class="value">{{ billForm.teamName }}</text>
</view>
<view class="header-item">
<text class="label">理货员</text>
<text class="value">{{ billForm.operatorName }}</text>
</view>
<!-- <view class="header-item total">
<text class="label">总数量</text>
<text class="value">2</text>
</view> -->
</view>
<!-- 物料明细列表 -->
<view class="material-list">
<!-- <view class="list-title">物料明细</view> -->
<view class="material-item" v-for="(item, index) in detailList" :key="index">
<view class="material-header">
<text class="material-code">物料号{{ item.wlNo }}</text>
</view>
<view class="info-item">
<text class="info-label">订单号</text>
<text class="info-value">{{ item.sapNo }}</text>
</view>
<view class="info-item">
<text class="info-label">物料描述</text>
<text class="info-value">{{ item.wlMs}}</text>
</view>
<view class="info-item">
<text class="info-label">数量</text>
<text class="info-value">{{ item.realQty }}</text>
</view>
<view class="info-item">
<text class="info-label">存放位置</text>
<text class="info-value">{{ item.pcode || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">项目号</text>
<text class="info-value">{{ item.xmNo || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">项目描述</text>
<text class="info-value">{{ item.xmMs || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">供应商</text>
<text class="info-value">{{ item.gysMc || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">备注</text>
<text class="info-value">{{ item.remark || '-' }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { ref, getCurrentInstance } from 'vue'
import { stockDetail } from '@/api/storage'
const storageType = ref("")
const billForm = ref({
billNo: "",
operationTypeName: "",
wlTypeName: "",
operationTime: "",
teamName: "",
operatorName: "",
})
const detailList = ref([])
onLoad((options)=>{
storageType.value = options.type
const instance = getCurrentInstance().proxy
const eventChannel = instance.getOpenerEventChannel();
eventChannel.on('acceptDataFrom', (data) => {
billForm.value = data.data
stockDetail(billForm.value.billNo).then(res => {
detailList.value = res.data
})
});
})
</script>
<style lang="scss" scoped>
.receipt-detail-container {
background-color: #f5f7fa;
min-height: 100vh;
padding: 0 20rpx 20rpx;
}
/* 头部信息卡片 */
.header-card {
background-color: #fff;
margin: 20rpx 0;
padding: 30rpx;
border-radius: 16rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
.header-item {
display: flex;
margin-bottom: 20rpx;
font-size: 28rpx;
&:last-child {
margin-bottom: 0;
}
.label {
color: #666;
width: 150rpx;
flex-shrink: 0;
}
.value {
color: #333;
flex: 1;
}
&.total {
.label {
font-weight: 500;
color: #333;
}
.value {
font-weight: 500;
color: #1890ff;
}
}
}
}
.list-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
margin-bottom: 20rpx;
}
/* 物料明细列表 */
.material-list {
.material-item {
background-color: #fffbe6;
border: 1rpx solid #ffe58f;
border-radius: 12rpx;
padding: 24rpx;
margin-bottom: 20rpx;
.material-header {
margin-bottom: 16rpx;
.material-code {
font-size: 30rpx;
font-weight: 500;
color: #d48806;
}
}
.info-item {
margin-bottom: 12rpx;
font-size: 26rpx;
&:last-child {
margin-bottom: 0;
}
.info-label {
color: #666;
width: 160rpx;
flex-shrink: 0;
}
.info-value {
color: #333;
flex: 1;
}
}
}
}
</style>

View File

@@ -0,0 +1,328 @@
<template>
<view class="container">
<z-paging ref="pagingRef" class="containerBox" v-model="localListData" :auto="false"
:default-page-size="queryParams.pageSize" @query="handleQuery">
<template #top>
<uv-search v-model="queryParams.billNo" placeholder="请输入" :showAction="true" actionText="搜索"
@search="handleSearch" @custom="handleSearch"></uv-search>
<view class="dropDown">
<view class="item_dropDown" @tap="openPicker">
<uv-text :lines="1" :text="storageTypeText" :color="storageTypeText != '全部' ? '#3c9cff' : ''"
class="item_text"></uv-text>
<uv-icon name="arrow-down-fill" :color="storageTypeText != '全部' ? '#3c9cff' : '#666'"></uv-icon>
</view>
<view class="item_dropDown" @tap="openPickerStatus">
<uv-text :lines="1" :text="storageStatusText" :color="storageStatusText != '全部' ? '#3c9cff' : ''"
class="item_text"></uv-text>
<uv-icon name="arrow-down-fill" :color="storageStatusText != '全部' ? '#3c9cff' : '#666'"></uv-icon>
</view>
</view>
</template>
<view class="box">
<view v-for="item in localListData" class="item" @tap="itemDetail(item)">
<view class="title">
<view class="sign" v-show="item.execStatus == 0">{{ item.execStatus == 0 ? '' : '' }}</view>
单据号{{ item.billNo }}
<!-- <uv-icon name="file-text" size="36rpx" style="margin-top: 4rpx;" @tap="itemCopy(item.billNo)"></uv-icon> -->
</view>
<!-- <view class="title" v-if="props.pickerCode == 'ckType'">单据号:{{ item.billNoCk }}<uv-icon name="file-text"
size="36rpx" style="margin-top: 4rpx;" @tap="itemCopy(item.billNoCk)"></uv-icon></view> -->
<!-- <view><text>订单号</text>{{ item.sapNo }}</view> -->
<view>
<text>{{ props.pickerCode == 'rkType' ? '入库类型' : '出库类型' }}</text>
{{ item.operationTypeName }}
</view>
<view v-if="props.pickerCode == 'rkType'"><text>物资类型</text>{{ item.wlTypeName }}</view>
<view><text>理货员</text>{{ item.operatorName }}</view>
<view v-if="props.pickerCode == 'ckType'"><text>施工队</text>{{ item.teamName }}</view>
<view><text>{{ props.pickerCode == 'rkType' ? '入库时间' : '出库时间' }}</text>{{ item.operationTime }}</view>
<!-- <view v-show="item.showMore">
<view><text>物料号</text>{{ item.wlNo }}</view>
<view><text>物料描述</text>{{ item.wlMs }}</view>
<view><text>数量</text>{{ item.realQty }}{{ item.dw }}</view>
<view><text>项目定义号</text>{{ item.xmNo }}</view>
<view><text>项目描述</text>{{ item.xmMs }}</view>
<view><text>供应商</text>{{ item.gysMc }}</view>
<view><text>存放位置</text>{{ item.pcode || "-" }}</view>
<view><text>身份码</text>{{ item.entityId || "-" }}</view>
<view v-if="props.pickerCode == 'rkType'"><text>备注:</text>{{ item.remark || "-" }}</view>
<view v-if="props.pickerCode == 'ckType'"><text>备注:</text>{{ item.ckRemark || "-" }}</view>
</view>
<view class="more" v-show="!item.showMore" @tap="changeMore(item)">
<view>详细信息</view>
<uv-icon name="arrow-down" color="#A4A6A7" size="28rpx" style="margin-left: 10rpx;"></uv-icon>
</view>
<view class="more" v-show="item.showMore" @tap="changeMore(item)">
<view>收起</view>
<uv-icon name="arrow-up" color="#A4A6A7" size="28rpx" style="margin-left: 10rpx;"></uv-icon>
</view> -->
</view>
</view>
<view class="btn">
<!-- <uv-button type="error" text="确定" size="large" style="width: 48%;" @tap="openModal">{{ props.deleteText
}}</uv-button> -->
<uv-button type="primary" text="确定" size="large" class="mainBtn" style="width: 100%;" @tap="handleAdd">{{
props.GoText
}}</uv-button>
</view>
</z-paging>
<uv-picker ref="picker" :columns="storageType" keyName="typeName" activeColor="#3c9cff"
@confirm="pickerConfirm"></uv-picker>
<uv-picker ref="pickerStatus" :columns="storageStatus" keyName="label" activeColor="#3c9cff"
@confirm="pickerConfirmStatus"></uv-picker>
<uv-modal ref="storageModalRef" title="单据号" @confirm="handleRemove" :showCancelButton="true"
:closeOnClickOverlay="false" asyncClose>
<view class="slot-content" style="width: 100%;">
<uv-form labelPosition="left" :model="storageForm" labelWidth="80" :rules="storageRules" ref="storageFormRef">
<uv-form-item label="单据号" prop="billNo" borderBottom>
<uv-input v-model="storageForm.billNo" border="none" placeholder="请输入单据号" />
</uv-form-item>
</uv-form>
</view>
</uv-modal>
</view>
</template>
<script setup>
import { ref, watch } from 'vue';
// Props定义
const props = defineProps({
listData: {
type: Array,
default: () => []
},
storageType: {
type: Array,
default: () => []
},
storageStatus: {
type: Array,
default: () => []
},
pickerCode: {
type: String,
default: "rkType"
},
deleteText: {
type: String,
default: "打 开"
},
GoText: {
type: String,
default: "下一步"
},
queryByParams: {
type: Object,
default: () => { }
}
});
// Emits定义
const emit = defineEmits(['update:listData', 'remove', 'add', 'reload']);
// 本地数据
const localListData = ref([]);
const queryParams = ref(props.queryByParams);
queryParams.value[props.pickerCode] = "";
// 组件引用
const pagingRef = ref(null);
const storageModalRef = ref(null);
const storageFormRef = ref(null);
// 表单数据
const storageForm = ref({
billNo: '',
});
const storageRules = ref({
'billNo': {
type: 'string',
required: true,
message: '请填写单据号',
trigger: ['blur', 'change']
},
});
// 监听props变化
watch(() => props.listData, (newVal) => {
// localListData.value = newVal;
pagingRef.value.complete(newVal)
}, { deep: true });
// 方法定义
const handleQuery = (pageNo, pageSize) => {
emit('reload', { ...queryParams.value, pageNum: pageNo, pageSize });
};
const handleSearch = () => {
pagingRef.value.reload();
};
const picker = ref(null);
const storageTypeText = ref("全部");
const openPicker = () => {
picker.value.open();
};
const pickerConfirm = (e) => {
queryParams.value.operationType = e.value[0].typeCode;
storageTypeText.value = e.value[0].typeName;
pagingRef.value.reload();
};
const pickerStatus = ref(null);
const storageStatusText = ref("全部");
const openPickerStatus = () => {
pickerStatus.value.open();
};
const pickerConfirmStatus = (e) => {
queryParams.value.execStatus = e.value[0].value;
storageStatusText.value = e.value[0].label;
pagingRef.value.reload();
};
const itemCopy = (id) => {
uni.setClipboardData({
data: id,
success: function () { }
});
};
const changeMore = (item) => {
item.showMore = !item.showMore;
};
const openModal = () => {
storageForm.value.billNo = ""
storageModalRef.value.open();
};
const itemDetail = (item) => {
uni.navigateTo({
url: '/pagesStorage/storageDetail?type=' + props.pickerCode,
success: function(res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFrom', { data: item })
}
})
}
const handleRemove = () => {
storageFormRef.value.validate().then(res => {
emit('remove', storageForm.value.billNo);
storageModalRef.value.close();
}).catch(errors => {
storageModalRef.value.closeLoading();
});
};
const handleAdd = () => {
emit('add');
};
</script>
<style scoped lang="scss">
.container {
position: relative;
.containerBox {
padding: 32rpx;
padding-bottom: 120rpx;
.dropDown {
// padding: 0 30rpx;
border-bottom: 1px solid #dadbde;
display: flex;
.item_dropDown {
padding: 20rpx;
display: flex;
align-items: center;
width: 140rpx;
::v-deep .uv-text {
width: unset !important;
flex: unset !important;
}
::v-deep .item_text {
max-width: 200rpx;
margin-right: 10rpx !important;
}
}
}
::v-deep .uv-search {
flex: unset;
}
.box {
// background-color: #ebebeb;
// background-color: #f5f5f5;
// padding-top: 20rpx;
.item {
background: #efefef;
padding: 20rpx;
margin-top: 20rpx;
line-height: 50rpx;
font-size: 28rpx;
border-radius: 8rpx;
color: #333;
position: relative;
.title {
font-size: 32rpx;
font-weight: bold;
display: flex;
align-items: center;
}
.sign {
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
border-radius: 40rpx;
color: #fff;
background: #FF3800;
font-size: 24rpx;
font-weight: 400;
margin-right: 10rpx;
}
text {
color: #666;
}
.more {
color: #A4A6A7;
display: flex;
align-items: center;
}
}
}
.btn {
position: fixed;
width: calc(100vw - 64rpx);
bottom: 0;
left: 32rpx;
z-index: 99;
display: flex;
align-items: center;
justify-content: space-between;
}
}
::v-deep .uv-input__content {
flex-direction: column;
align-items: flex-start;
}
}
</style>