557 lines
18 KiB
Vue
Raw Normal View History

2025-08-29 17:25:42 +08:00
<template>
<el-dialog v-model="showDialog" title="采购订单审批" width="1200px" @close="closeDialog">
2025-09-05 16:03:24 +08:00
<el-form label-position="right" label-width="110px" v-loading="loading">
2025-08-29 17:25:42 +08:00
<el-form-item label="公司名称:">
<el-select v-model="itemInfo.company_id" placeholder="请选择" clearable filterable style="width: 320px;">
<el-option v-for="it in companyList" :key="it.id" :label="it.name" :value="it.id" />
</el-select>
</el-form-item>
<el-form-item label="选品:">
<el-select v-model="itemInfo.manager_id" placeholder="请选择" clearable filterable style="width: 320px;">
<el-option v-for="it in managerList" :key="it.id" :label="it.username" :value="it.id" />
</el-select>
</el-form-item>
<el-form-item label="供应商名称:">
<el-select v-model="itemInfo.purchase_supplier_id" placeholder="请选择" clearable filterable style="width: 320px;">
<el-option v-for="it in supplierList" :key="it.id" :label="it.supplier_name" :value="it.id" />
</el-select>
</el-form-item>
<el-form-item label="商品信息:">
<el-button type="primary" @click="openGoods()">添加商品</el-button>
<el-table :data="goodsList" style="width: 100%;margin-top: 15px;" border>
<el-table-column prop="goods.title" label="商品名称" />
<el-table-column label="规格名称">
<template #default="scope">
<span>{{ scope.row.sku && scope.row.sku.title || scope.row.title }}</span>
</template>
</el-table-column>
<el-table-column label="预计产品单价(含税)" align="center">
<template #default="scope">
2025-09-05 16:03:24 +08:00
<el-input class="inpt" type="text" v-model="scope.row.expect_unit_price" @input="blurInput(scope.row)" />
2025-08-29 17:25:42 +08:00
</template>
</el-table-column>
<el-table-column label="单位" align="center">
<template #default="scope">
<el-input class="inpt" type="text" v-model="scope.row.unit" />
</template>
</el-table-column>
<el-table-column label="预计采购数量" align="center">
<template #default="scope">
2025-09-05 16:03:24 +08:00
<el-input class="inpt" type="text" v-model="scope.row.expect_quantity" @input="blurInput(scope.row)" />
2025-08-29 17:25:42 +08:00
</template>
</el-table-column>
<el-table-column label="预付款比例(%)" align="center">
<template #default="scope">
2025-09-05 16:03:24 +08:00
<div style="display: flex;align-items: center;">
<el-input type="text" class="inpt" v-model="scope.row.prepayment_ratio" @input="blurInput(scope.row)" />&nbsp;%
</div>
2025-08-29 17:25:42 +08:00
</template>
</el-table-column>
<el-table-column label="交货时间" width="160" align="center">
<template #default="scope">
<el-date-picker
v-model="scope.row.delivery_date"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
placeholder="选择日期"
style="width: 130px;"
clearable>
</el-date-picker>
</template>
</el-table-column>
2025-09-05 16:03:24 +08:00
<el-table-column label="预计订单金额(元)" align="center" prop="estimated_order_amount" />
<el-table-column label="预付款(元)" align="center" prop="advance_payment" />
<el-table-column label="尾款(元)" align="center" prop="balance_payment" />
<el-table-column label="操作" align="center" width="60">
2025-08-29 17:25:42 +08:00
<template #default="scope">
2025-09-05 16:03:24 +08:00
<el-button type="text" @click="removeGoods(scope.$index, scope.row.id)"><el-icon color="#f00"><DeleteFilled /></el-icon></el-button>
2025-08-29 17:25:42 +08:00
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="其他费用:">
<el-button type="primary" @click="addFee">添加其他费用</el-button>
<el-table :data="feesList" style="width: 100%;margin-top: 15px;" border>
<el-table-column label="费用名称" align="center">
<template #default="scope">
<el-input type="text" v-model="scope.row.fee_name" />
</template>
</el-table-column>
<el-table-column label="订单金额">
<template #default="scope">
2025-09-05 16:03:24 +08:00
<el-input type="text" v-model="scope.row.amount" @input="getSumData()" />
2025-08-29 17:25:42 +08:00
</template>
</el-table-column>
<el-table-column label="打款信息">
<template #default="scope">
<el-select v-model="scope.row.other_expense_account_id" placeholder="请选择" clearable filterable>
<el-option v-for="it in accountList" :key="it.id" :label="it.name" :value="it.id" />
</el-select>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<el-button type="danger" size="mini" @click="removeFee(scope.$index)"><el-icon><DeleteFilled /></el-icon></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="备注:">
<el-input v-model="itemInfo.remark" placeholder="请填写备注内容" type="textarea" :rows="4"></el-input>
</el-form-item>
<el-form-item label="逾期交货说明:">
<el-input v-model="itemInfo.late_delivery_explanation" placeholder="请填写逾期交货说明" type="textarea" :rows="4"></el-input>
</el-form-item>
<el-form-item label="总计:">
2025-09-05 16:03:24 +08:00
<div class="sumbox" >
2025-08-29 17:25:42 +08:00
总预计订单金额<span>{{ sumData.total_amount || '0.00' }}</span>
总预付款<span>{{ sumData.pre_pay_amount || '0.00' }}</span>
总尾款<span>{{ sumData.balance_amount || '0.00' }}</span>
</div>
</el-form-item>
2025-09-05 16:03:24 +08:00
2025-08-29 17:25:42 +08:00
<div class="space"></div>
<div class="h5Tit">其余信息</div>
<el-form-item label="开团时间:">
<el-date-picker
v-model="itemInfo.sold_start_time"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择开团时间"
clearable>
</el-date-picker>
</el-form-item>
<el-form-item label="预计到仓时间:">
<el-date-picker
v-model="itemInfo.arrived_time"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="预计到仓时间"
clearable>
</el-date-picker>
</el-form-item>
<el-form-item label="仓库:">
<el-input type="text" v-model="itemInfo.warehouse_name" placeholder="请输入仓库名称" clearable style="width: 320px;" />
</el-form-item>
</el-form>
<template #footer>
2025-09-05 16:03:24 +08:00
<span class="dialog-footer">
2025-08-29 17:25:42 +08:00
<el-button @click="closeDialog()">取消</el-button>
<el-button type="primary" @click="commitApproval()" :loading="btnloading">提交审批</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="showGoods" width="900px" title="添加商品">
<div class="searchBox">
<div class="row">
<span class="span">商品名称</span>
<div class="right">
2025-09-05 16:03:24 +08:00
<el-select v-model="filter.goods_ids" placeholder="请选择" clearable filterable class="wid100">
2025-08-29 17:25:42 +08:00
<el-option v-for="it in goodskuList" :key="it.id" :label="it.title" :value="it.id" />
</el-select>
</div>
</div>
<div class="row">
<span class="span">规格名称</span>
<div class="right"><el-input v-model="filter.title" class="wid100" clearable></el-input></div>
</div>
<div class="row">
<span class="span">规格编码</span>
<div class="right"><el-input v-model="filter.sku_code" class="wid100" clearable></el-input></div>
</div>
<el-button type="primary" @click="handleSearch"><el-icon><Search /></el-icon>&nbsp;筛选</el-button>
</div>
<el-table :data="tableList" style="width: 100%" border v-loading="loading1" @select="select"
ref="multipleTable" @select-all="selectAll">
<el-table-column type="selection" width="55" :selectable="checkSelect" />
<el-table-column prop="id" label="ID" width="80" align="center" />
<el-table-column prop="goods.title" label="商品名称" align="center" />
<el-table-column prop="goods.goods_code" label="商品货号" align="center" />
<el-table-column prop="title" label="规格名称" align="center" />
<el-table-column prop="sku_code" label="规格编码" align="center" />
</el-table>
<div class="page-pagination">
<el-pagination
:current-page="page"
background
layout="prev, pager, next, sizes, total"
:total="total"
:page-sizes="[10, 50, 100]"
:page-size="pageSize"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"></el-pagination>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="showGoods = false">取消</el-button>
<el-button type="primary" @click="addGoods">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { DeleteFilled, Search } from "@element-plus/icons"
import { reactive, toRefs, watch } from 'vue'
import { get, post } from '@/api/request'
import { ElMessage, ElMessageBox } from 'element-plus'
export default {
components: { DeleteFilled, Search },
props: {
show: {
type: Boolean,
default: false
},
id: {
type: Number,
default: 0,
}
},
setup(props, context) {
const data = reactive({
launchId: 0,
showDialog: false,
companyList: [],
managerList: [],
supplierList: [],
accountList: [],
goodsList: [],
itemInfo: {},
loading: false,
showGoods: false,
feesList: [],
goodskuList: [],
filter: {},
tableList: [],
page: 1,
pageSize: 10,
total: 0,
loading1: false,
chooseList: [],
btnloading: false,
goodsIds: [],
sumData: {}
})
function getDetail() {
data.loading = true
get(`/api/purchaseOrder/${data.launchId}`).then((res) => {
data.itemInfo = res.data
2025-09-05 16:03:24 +08:00
data.sumData.total_amount = res.data.expect_amount
data.sumData.pre_pay_amount = res.data.prepayment_amount
data.sumData.balance_amount = res.data.final_payment_amount
2025-08-29 17:25:42 +08:00
data.feesList = res.data.other_expenses
res.data.products.forEach((item) => {
2025-09-05 16:03:24 +08:00
data.goodsIds.push(item.id)
if(item.expect_unit_price && item.expect_quantity) {
item.estimated_order_amount = (item.expect_unit_price * item.expect_quantity).toFixed(2)
if(item.prepayment_ratio) {
item.advance_payment = ((item.estimated_order_amount * item.prepayment_ratio) / 100).toFixed(2)
item.balance_payment = (((item.estimated_order_amount * 100) - (item.advance_payment * 100)) / 100).toFixed(2)
}
}
2025-08-29 17:25:42 +08:00
})
2025-09-05 16:03:24 +08:00
data.goodsList = res.data.products
2025-08-29 17:25:42 +08:00
data.loading = false
}).catch(() => {
data.loading = false
})
}
function getCompany() {
get(`/api/company/all`, {page: 1, pageSize: 1000}).then((res) => {
data.companyList = res.data
})
}
function getManagerList() {
get('/api/staff', {role_id: 1}).then((res) => {
data.managerList = res.data
})
}
function getSupplier() {
get(`/api/purchaseSupplier`, {page: 1, pageSize: 1000}).then((res) => {
data.supplierList = res.data
})
}
function getAccount() {
get(`/api/otherExpenseAccount`, {page: 1, pageSize: 1000}).then((res) => {
data.accountList = res.data
})
}
const commitApproval = () => {
data.btnloading = true
let products = []
for (let index = 0; index < data.goodsList.length; index++) {
let obj = data.goodsList[index]
products.push({
product_id: obj.goods_id,
sku_id: obj.sku_id,
expect_unit_price: obj.expect_unit_price,
expect_quantity: obj.expect_quantity,
unit: obj.unit,
prepayment_ratio: obj.prepayment_ratio,
delivery_date: obj.delivery_date
})
}
let params = {
company_id: data.itemInfo.company_id,
manager_id: data.itemInfo.manager_id,
purchase_supplier_id: data.itemInfo.purchase_supplier_id,
products: products,
otherExpenses: data.feesList,
remark: data.itemInfo.remark,
late_delivery_explanation: data.itemInfo.late_delivery_explanation,
sold_start_time: data.itemInfo.sold_start_time,
arrived_time: data.itemInfo.arrived_time,
warehouse_name: data.itemInfo.warehouse_name
}
post(`/api/purchaseOrder`, params).then((res) => {
ElMessage({ type: 'success', message: '操作成功' })
closeDialog()
context.emit('refresh')
data.btnloading = false
}).catch(() => {
data.btnloading = false
})
}
function clearForm() {
data.itemInfo = {}
data.feesList = []
data.goodsList = []
data.goodsIds = []
}
function getGoodskuList() {
get(`/api/all/goods`).then((res) => {
data.goodskuList = res.data
})
}
function handleSearch() {
data.page = 1
fetchData()
}
const fetchData = () => {
data.loading1 = true
let params = {
page: data.page,
pageSize: data.pageSize,
...data.filter,
}
get(`/api/goods-skus`, params).then((res) => {
data.tableList = res.data
data.total = res.meta.total
data.loading1 = false
data.chooseList = []
}).catch(() => {
data.loading1 = false
})
}
function handleCurrentChange(e) {
data.page = e
fetchData()
}
function handleSizeChange(e) {
data.page = 1
data.pageSize = e
fetchData()
}
const closeDialog = () => {
clearForm()
context.emit('close')
data.showDialog = false
}
function select(e) {
data.chooseList = e
}
function selectAll(e) {
data.chooseList = e
}
function checkSelect(row) {
if (data.goodsIds.indexOf(row.id) >= 0) {
return false
} else {
return true
}
}
function addGoods() {
if(!data.chooseList.length) {
return ElMessage.info('请选择商品')
}
data.chooseList.forEach((item) => {
item.product_id = item.goods_id
item.sku_id = item.id
data.goodsList.push(item)
2025-09-05 16:03:24 +08:00
data.goodsIds.push(item.id)
2025-08-29 17:25:42 +08:00
})
data.showGoods = false
}
function removeGoods(i, id) {
data.goodsList.splice(i, 1)
let index = data.goodsIds.indexOf(id)
data.goodsIds.splice(index, 1)
}
function addFee() {
data.feesList.push({
fee_name: '',
amount: '',
other_expense_account_id: ''
})
}
function removeFee(i) {
data.feesList.splice(i, 1)
}
function openGoods() {
data.showGoods = true
handleSearch()
}
2025-09-05 16:03:24 +08:00
function blurInput(row) {
if(row.expect_unit_price && row.expect_quantity) {
row.estimated_order_amount = (row.expect_unit_price * row.expect_quantity).toFixed(2)
if(row.prepayment_ratio) {
row.advance_payment = ((row.estimated_order_amount * row.prepayment_ratio) / 100).toFixed(2)
row.balance_payment = (((row.estimated_order_amount * 100) - (row.advance_payment * 100)) / 100).toFixed(2)
}
}
}
2025-08-29 17:25:42 +08:00
watch(() => data.goodsList, (newProps) => {
2025-09-05 16:03:24 +08:00
getSumData()
}, { deep: true })
function getSumData() {
if(data.launchId) {
return
}
let num1 = 0, num2 = 0
for (let index = 0; index < data.goodsList.length; index++) {
let item = data.goodsList[index]
2025-08-29 17:25:42 +08:00
if(item.expect_unit_price && item.expect_quantity) {
2025-09-05 16:03:24 +08:00
num1 += item.expect_unit_price * item.expect_quantity * 100
2025-08-29 17:25:42 +08:00
if(item.prepayment_ratio) {
num2 += num1 * item.prepayment_ratio
}
}
}
2025-09-05 16:03:24 +08:00
for (let index = 0; index < data.feesList.length; index++) {
let item = data.feesList[index]
if(item.amount * 1 > 0) {
num1 += item.amount * 100
num2 += item.amount * 10000
}
}
data.sumData.total_amount = (num1 / 100).toFixed(2)
data.sumData.pre_pay_amount = (num2 / 10000).toFixed(2)
data.sumData.balance_amount = (((data.sumData.total_amount * 100) - (data.sumData.pre_pay_amount * 100)) / 100).toFixed(2)
}
2025-08-29 17:25:42 +08:00
watch(() => props, (newProps) => {
if (newProps.show) {
data.showDialog = true
data.launchId = newProps.id
if(data.launchId) {
getDetail()
}
getCompany()
getManagerList()
getSupplier()
getGoodskuList()
getAccount()
}
}, { deep: true })
return {
...toRefs(data),
getDetail,
getAccount,
closeDialog,
getCompany,
getManagerList,
getSupplier,
clearForm,
commitApproval,
getGoodskuList,
handleSearch,
handleCurrentChange,
handleSizeChange,
select,
selectAll,
checkSelect,
addGoods,
removeGoods,
addFee,
removeFee,
2025-09-05 16:03:24 +08:00
openGoods,
blurInput,
getSumData
2025-08-29 17:25:42 +08:00
}
}
}
</script>
<style scoped lang="scss">
.searchBox{
display: flex;
flex-wrap: wrap;
background-color: #fff;
padding: 15px 0 0 0;
border-radius: 4px;
margin-bottom: 15px;
.row{
display: flex;
align-items: center;
width: 250px;
box-sizing: border-box;
margin-bottom: 15px;
.span{
display: block;
width: 80px;
font-size: 14px;
text-align: right;
box-sizing: border-box;
}
.right{
width: calc(100% - 100px);
}
.wid100{
width: 100%;
}
}
}
.space{
background: repeating-linear-gradient(-45deg, #F56C6C 0, #F56C6C 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
height: 2px;
background-size: 80px;
margin-bottom: 20px;
}
::v-deep .inpt .el-input__inner{
text-align: center;
}
</style>