Files
shuyuanuinapp/src/addon/erp/pages/inbound/order/add.vue
郑彪辉 07ac63b5bb 修改bug
2025-04-23 23:51:02 +08:00

524 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="bg-[var(--page-bg-color)] min-h-[100vh] overflow-hidden form-edit" :style="themeColor()">
<up-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef"
labelWidth="180rpx">
<view class="sidebar-margin card-template mt-[var(--top-m)] py-[20rpx]">
<view>
<up-form-item :label="t('code')" prop="code" required borderBottom>
<u-input fontSize="28rpx" v-model.trim="formData.code" disabled clearable
placeholderStyle="color: #888" :placeholder="t('codePlaceholderNew')" />
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="t('supplierId')" prop="supplier_id" required borderBottom>
<!-- #ifdef H5 -->
<zxz-uni-data-select v-model="formData.supplier_id" :localdata="supplierList" dataKey="name" dataValue="id"
:clear="false" placeholder="请选择供应商" @change="supplierIdChange"/>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<wht-select v-model="formData.supplier_id" :options="supplierList" dataKey="name" dataValue="id" placeholder="请选择供应商" :height="38" @change="supplierIdChange"/>
<!-- #endif -->
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="t('warehouseId')" prop="warehouse_id" required borderBottom>
<!-- #ifdef H5 -->
<zxz-uni-data-select v-model="formData.warehouse_id" :localdata="warehouseList" dataKey="name" dataValue="id"
:clear="false" placeholder="请选择仓库" @change="warehouseIdChange"/>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<wht-select v-model="formData.warehouse_id" :options="warehouseList" dataKey="name" dataValue="id" placeholder="请选择仓库" :height="38" @change="warehouseIdChange"/>
<!-- #endif -->
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="t('type')" prop="type" borderBottom>
<!-- #ifdef H5 -->
<zxz-uni-data-select v-model="formData.type" :localdata="typeList" dataKey="name" dataValue="name"
:clear="false" placeholder="请选择交货方式" @change="updateType"/>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<wht-select v-model="formData.type" :options="typeList" dataKey="name" dataValue="name" :defaultVal="formData.type" placeholder="请选择交货方式" :height="38" @change="updateType"/>
<!-- #endif -->
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="'到货日期'" prop="delivery_time" borderBottom @click="deliveryTimeShow = true">
<up-datetime-picker hasInput :show="deliveryTimeShow" v-model="formData.delivery_time" mode="date" :placeholder="t('deliveryTimePlaceholder')" format="YYYY-MM-DD" @confirm="deliveryTimeConfirm"></up-datetime-picker>
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="t('billingTime')" prop="billing_time" borderBottom @click="billingTimeShow = true">
<up-datetime-picker hasInput :show="billingTimeShow" v-model="formData.billing_time" mode="date" :placeholder="t('billingTimePlaceholder')" format="YYYY-MM-DD" @confirm="billingTimeConfirm"></up-datetime-picker>
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="t('batchNumber')" prop="batch_number" required borderBottom>
<u-input fontSize="28rpx" v-model.trim="formData.batch_number" clearable
placeholderStyle="color: #888" :placeholder="t('batchNumberPlaceholder')" />
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="t('remark')" prop="remark">
<u-textarea fontSize="28rpx" v-model="formData.remark" :placeholder="t('remarkPlaceholder')"
></u-textarea>
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="t('inboundImage')" prop="inbound_image">
<up-upload
:fileList="inbinboundImageFileList"
@afterRead="afterRead"
multiple
:maxCount="5"
accept="image"
></up-upload>
</up-form-item>
</view>
<view class="mt-[16rpx]">
<up-form-item :label="t('inspectionReportImage')" prop="inspection_report_image">
<up-upload
:fileList="inspectionReportImageFileList"
@afterRead="inspectionReportImageAfterRead"
multiple
:maxCount="5"
accept="image"
:capture="['camera']"
></up-upload>
</up-form-item>
</view>
</view>
<view class="mx-[var(--sidebar-m)] bg-[#ffffff] rounded mt-[20rpx]">
<view class="flex justify-between py-[10rpx] px-[20rpx] box-border border-0 border-b-1 border-color-[#dadbde] border-solid
">
<view class="text-base font-bold">{{t('Enter product')}}</view>
<view><u-button @click="goProductSelect" icon="plus" type="primary" :plain="true" size="mini"
:text="t('Add product')"></u-button>
</view>
</view>
<view v-if="formData.product.length > 0" class="sidebar-margin mt-[20rpx] pb-[20rpx] body-bottom">
<view class="mb-[15rpx]" v-for="(item, index) in formData.product" :key="index">
<view class="bg-[#ffffff] rounded-10rpx">
<view class="head border-0 border-b-1 border-solid border-[#ddd]">
<view class="flex justify-between p-[20rpx]">
<view class="u-body-item-title u-line-2">{{item.name}}</view>
<view><u-button :plain="true" type="error" @click="hanldeDelete(index)"
:text="t('delete')" size="mini"></u-button></view>
</view>
</view>
<view class="body">
<view class="flex justify-start flex-col p-[20rpx]">
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('productCode') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.code}}</text>
</view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('productTypeId') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.productType?.name}}</text>
</view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('spec') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.spec}}</text>
</view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('productUnitId') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.productUnit?.name}}</text>
</view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
<view class="content-center">
{{ t('purchasePrice') }}:
</view>
<view class="ml-[20rpx]">
<u-number-box min="0" v-model="item.purchase_price" :integer="true"
inputWidth="80"></u-number-box>
</view>
</view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
<view class="content-center">
有效期():
</view>
<view class="ml-[20rpx]">
<u-number-box min="0" v-model="item.expiry_term" :integer="true"
inputWidth="80"></u-number-box>
</view>
</view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
<view class="content-center">
{{ t('purchaseQuantity') }}:
</view>
<view class="ml-[20rpx]">
<u-number-box min="1" v-model="item.inbound_quantity" :integer="true"
inputWidth="80"></u-number-box>
</view>
</view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('totalPrice') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{ item.inbound_quantity * item.purchase_price }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view v-else class="sidebar-margin mt-[20rpx] body-bottom text-center">
<text class="text-sm text-color-[#848484]">暂未选择食材</text>
</view>
</view>
</up-form>
<view class="w-full footer">
<view
class="py-[var(--top-m)] px-[var(--sidebar-m)] footer w-full fixed bottom-0 left-0 right-0 box-border">
<button hover-class="none"
class="!bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500"
@click="handSave" :disabled="loading" :class="{'opacity-50': loading}">{{t('save')}}</button>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { t } from '@/locale'
import { onLoad, onReady } from '@dcloudio/uni-app';
import { getSupplierSelect, getWarehouseSelect } from '@/addon/erp/api/base';
import { addManual } from '@/addon/erp/api/purchase';
import { generatedCode } from '@/addon/erp/utils/common';
import {uploadImage } from '@/app/api/system'
import { redirect } from '@/utils/common';
import dayjs from 'dayjs'
interface FileItem {
url: string;
status?: string;
message?: string;
}
const formRef : any = ref(null)
const loading = ref(false)
const rules = reactive({
// 'supplier_id': {
// required: true,
// message: t('supplierIdPlaceholder'),
// trigger: ['blur', 'change'],
// },
// 'warehouse_id': {
// required: true,
// message: t('warehouseIdPlaceholder'),
// trigger: ['blur', 'change'],
// }
})
const formData = ref({
id: "",
code: generatedCode("RK"),
supplier_id: "",
supplier_name: "",
delivery_time: dayjs().format('YYYY-MM-DD'),
type: "送货上门",
warehouse_id: "",
warehouse_name: "",
billing_time: dayjs().format('YYYY-MM-DD'),
remark: "",
product: [] as any[],
batch_number: generatedCode('BN'),
inbound_image:"",
inspection_report_image:"",
total_num:0,
total_amount:0,
})
const typeList = ref([
{
name: '送货上门'
},
{
name: '到店自提'
},
{
name: '邮寄配送'
}
])
const inbinboundImageFileList=ref<FileItem[]>([])
const inspectionReportImageFileList=ref<FileItem[]>([])
onReady(() => {
formRef.value.setRules(rules);
})
// 页面加载
onLoad((option : any) => {
getSupplierList();
getWarehouseList();
// 接收子页面传值
uni.$on('choose_product', res => {
const uniqueItems : any = {};
formData.value.product.forEach(item => {
uniqueItems[item.code] = item;
});
res.forEach((item:any) => {
if (!uniqueItems[item.code]) {
uniqueItems[item.code] = item;
}
});
const uniqueArray = Object.values(uniqueItems);
formData.value.product = uniqueArray.map((item:any) => {
item.purchase_price = 0;
item.inbound_quantity = 1;
item.expiry_term=item.expiry_term || 0
item.unit = item.productUnit?.name
return item;
});
})
})
const afterRead = async (event: any) => {
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
let lists:FileItem[] = [].concat(event.file) ;
let fileListLen = inbinboundImageFileList.value.length;
lists = lists.filter((item:FileItem) => item.url);
lists.map((item: any) => {
inbinboundImageFileList.value.push({
url: item.url,
status: 'uploading',
message: '上传中',
});
})
for (let i = 0; i < lists.length; i++) {
const result = await uploadFilePromise(lists[i].url);
let item = inbinboundImageFileList.value[fileListLen];
inbinboundImageFileList.value.splice(fileListLen, 1, {
...item,
status: 'success',
message: '',
url: result as string,
});
fileListLen++;
}
}
const inspectionReportImageAfterRead = async (event: any) => {
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
let lists:FileItem[] = [].concat(event.file) ;
let fileListLen = inspectionReportImageFileList.value.length;
lists = lists.filter((item:FileItem) => item.url);
lists.map((item: any) => {
inspectionReportImageFileList.value.push({
url: item.url,
status: 'uploading',
message: '上传中',
});
})
for (let i = 0; i < lists.length; i++) {
const result = await uploadFilePromise(lists[i].url);
let item = inspectionReportImageFileList.value[fileListLen];
inspectionReportImageFileList.value.splice(fileListLen, 1, {
...item,
status: 'success',
message: '',
url: result as string,
});
fileListLen++;
}
}
const uploadFilePromise = (url: any) => {
return new Promise((resolve, reject) => {
let a = uploadImage({
filePath:url,
name: 'file'
}).then((res:any)=>{
setTimeout(() => {
resolve(res.data.url as string);
}, 1000);
})
});
}
const updateType = (e : any) => {
formData.value.type = e.name;
}
/**
* 供应商
*/
const supplierList = ref<any[]>([]);
const supplierIdChange = (e : any) => {
formData.value.supplier_id = e.id;
formData.value.supplier_name = e.name;
if (formRef.value) {
formRef.value.validateField('supplier_id');
}
}
// 获取供应商
const getSupplierList = () => {
getSupplierSelect({}).then((res : any) => {
supplierList.value = res.data;
}).catch(err => {
// 如果是4001没有绑定企业账号强制跳转绑定
if (err.code == 4001) {
redirect({ url: '/addon/erp/pages/member/bind' })
}
})
}
/**
* 仓库
*/
const warehouseList = ref<any[]>([]);
const warehouseIdChange = (e : any) => {
formData.value.warehouse_id = e.id;
formData.value.warehouse_name = e.name;
if (formRef.value) {
formRef.value.validateField('warehouse_id');
}
}
// 获取仓库
const getWarehouseList = () => {
getWarehouseSelect({}).then((res : any) => {
warehouseList.value = res.data;
}).catch(err => {
// 如果是4001没有绑定企业账号强制跳转绑定
if (err.code == 4001) {
redirect({ url: '/addon/erp/pages/member/bind' })
}
})
}
// 跳转到食材选择页
const goProductSelect = () => {
if (!formData.value.warehouse_id) {
uni.showToast({ icon: 'none', title: t('warehouseIdPlaceholder') })
return false;
}
return redirect({
url: '/addon/erp/pages/product/product/product-select',
param: {
type: 'all'
},
})
}
/**
* 交货日期
*/
const deliveryTimeShow = ref(false);
const deliveryTimeConfirm = (e : any) => {
formData.value.delivery_time = uni.$u.date(e.value, 'yyyy-mm-dd');
deliveryTimeShow.value = false;
}
/**
* 制单日期
*/
const billingTimeShow = ref(false);
const billingTimeConfirm = (e : any) => {
formData.value.billing_time = uni.$u.date(e.value, 'yyyy-mm-dd');
billingTimeShow.value = false;
}
// 删除
const hanldeDelete = (index : number) => {
formData.value.product.splice(index, 1);
}
// 总金额
const totalData = computed(() => {
let data = {
money: 0,
nums: 0,
};
for (let item of formData.value.product) {
let amount = Number(item.inbound_quantity) * Number(item.purchase_price);
data.money += amount;
data.nums += Number(item.inbound_quantity);
}
return data;
});
// 保存
const handSave = () => {
if (loading.value) return
if (!formData.value.code) {
uni.showToast({ icon: 'none', title: t('codePlaceholderNew') })
return false;
}
if (!formData.value.supplier_id) {
uni.showToast({ icon: 'none', title: t('supplierIdPlaceholder') })
return false;
}
if (!formData.value.warehouse_id) {
uni.showToast({ icon: 'none', title: t('warehouseIdPlaceholder') })
return false;
}
if (!formData.value.batch_number) {
uni.showToast({ icon: 'none', title: t('batchNumberPlaceholder') })
return false;
}
loading.value = true
formData.value.total_num = totalData.value.nums;
formData.value.total_amount = totalData.value.money;
formData.value.delivery_time = uni.$u.date(formData.value.delivery_time, 'yyyy-mm-dd');
formData.value.billing_time = uni.$u.date(formData.value.billing_time, 'yyyy-mm-dd');
if(inbinboundImageFileList.value.length > 0){
const imgUrls=inbinboundImageFileList.value.map((item:any)=>item.url)
formData.value.inbound_image=imgUrls.join(',')
}
if(inspectionReportImageFileList.value.length > 0){
const imgUrls=inspectionReportImageFileList.value.map((item:any)=>item.url)
formData.value.inspection_report_image=imgUrls.join(',')
}
addManual(formData.value).then((res : any) => {
loading.value = false
if (res.code == 1) {
redirect({ url: '/addon/erp/pages/inbound/order/list' })
}
}).catch((err) => {
// 如果是4001没有绑定企业账号强制跳转绑定
if (err.code == 4001) {
redirect({ url: '/addon/erp/pages/member/bind' })
}
loading.value = false
})
// console.log("formRef.value", formRef.value);
// console.log("formData.value", formData.value);
// return;
// formRef.value.validate().then(() => {
// }).catch(err => {
// console.log("err", err);
// })
}
</script>
<style lang="scss" scoped>
.form-edit :deep(.up-form-item__body__left__content__label) {
font-size: 28rpx !important;
}
.form-edit :deep(.up-form-item__body__right) {
display: flex;
align-items: center;
}
.footer {
height: calc(100rpx + var(--top-m) + var(--top-m) + constant(safe-area-inset-bottom)) !important;
height: calc(100rpx + var(--top-m) + var(--top-m) + env(safe-area-inset-bottom)) !important;
}
</style>