feat(inventory): 添加订单执行跟踪功能

- 新增库存管理路由模块- 实现订单执行列表页面
- 支持订单执行编辑功能
- 配置相应权限控制
- 优化订单详情组件结构
- 提取基础信息为独立组件
- 简化表单处理逻辑- 移除冗余字典数据请求
dev_1.0.0
chenhao 2025-11-17 15:34:57 +08:00
parent 0e764c997b
commit bb35f25900
4 changed files with 907 additions and 1599 deletions

View File

@ -0,0 +1,359 @@
<template>
<el-row>
<el-col :span="16">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="localOrderData.projectName" placeholder="选择项目后带入" readonly :disabled="isReadonly">
<el-button slot="append" icon="el-icon-search" @click="$emit('select-project')" :disabled="isReadonly"></el-button>
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="版本号" prop="versionCode">
<el-input-number v-model="localOrderData.versionCode" :min="1" readonly :disabled="isReadonly" label="版本号" style="width:100%"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="localOrderData.projectCode" placeholder="选择项目后带入" readonly :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="最终客户" prop="customerName">
<el-input v-model="localOrderData.customerName" placeholder="选择项目后带入" readonly :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="BG" prop="bgProperty">
<el-select v-model="localOrderData.bgProperty" placeholder="请选择BG" @change="handleBgChange" :disabled="isReadonly">
<el-option v-for="dict in bgOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="行业" prop="industryType">
<el-select v-model="localOrderData.industryType" placeholder="请先选择BG" :disabled="isReadonly">
<el-option v-for="dict in industryOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="代表处" prop="agentName">
<el-input v-model="localOrderData.agentName" placeholder="选择项目后带入" readonly :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="进货商接口人" prop="businessPerson">
<el-input v-model="localOrderData.businessPerson" placeholder="请输入进货商接口人" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="Email" prop="businessEmail">
<el-input v-model="localOrderData.businessEmail" placeholder="请输入Email" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系方式" prop="businessPhone">
<el-input v-model="localOrderData.businessPhone" placeholder="请输入联系方式" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="合同编号" prop="orderCode">
<el-input v-model="localOrderData.orderCode" placeholder="自动生成" readonly :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="执行单截止时间" prop="orderEndTime">
<el-date-picker v-model="localOrderData.orderEndTime" type="date" value-format="yyyy-MM-dd" placeholder="审批完成后自动计算" disabled></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="币种" prop="currencyType">
<el-select v-model="localOrderData.currencyType" placeholder="请选择币种" :disabled="isReadonly">
<el-option v-for="dict in currencyOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col
v-if="(localOrderData.processTemplate=='1' ||(localOrderData.processTemplate!='1' &&( localOrderData.orderStatus=='1'||localOrderData.orderStatus=='2')))"
:span="8">
<el-form-item label="总代进货金额" prop="actualPurchaseAmount">
<el-input v-model="localOrderData.actualPurchaseAmount" readonly :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="(localOrderData.processTemplate=='1' ||(localOrderData.processTemplate!='1' &&( localOrderData.orderStatus=='1'||localOrderData.orderStatus=='2')))?8:16">
<el-form-item label="总代出货金额" prop="shipmentAmount">
<el-input v-model="localOrderData.shipmentAmount" placeholder="请输入金额" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="要求到货时间" prop="deliveryTime">
<el-date-picker clearable v-model="localOrderData.deliveryTime" type="date" value-format="yyyy-MM-dd"
placeholder="选择要求到货时间" :disabled="isReadonly">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="公司直发" prop="companyDelivery">
<el-select v-model="localOrderData.companyDelivery" placeholder="请选择" :disabled="isReadonly">
<el-option v-for="dict in companyDeliveryOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="下单通路" prop="orderChannel">
<el-select v-model="localOrderData.orderChannel" placeholder="请选择" @change="handleChannelChange" :disabled="isReadonly">
<el-option label="总代" value="1"></el-option>
<el-option label="直签" value="2"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" v-if="localOrderData.orderChannel == '1'">
<el-form-item label="总代" prop="zd">
<el-input value="广州佳都技术有限公司" readonly :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="localOrderData.orderChannel == '2' ? 16 : 8">
<el-form-item label="供货商" prop="supplier">
<el-input v-model="localOrderData.supplier" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="汇智责任人" prop="dutyName">
<el-input v-model="localOrderData.dutyName" placeholder="请选择责任人" :disabled="isReadonly" @click.native="!isReadonly && $emit('select-user')">
<el-button slot="append" icon="el-icon-search" @click.native="!isReadonly && $emit('select-user')" :disabled="isReadonly"></el-button>
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="Email" prop="dutyEmail">
<el-input v-model="localOrderData.dutyEmail" placeholder="请输入Email" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系方式" prop="dutyPhone">
<el-input v-model="localOrderData.dutyPhone" placeholder="请输入联系方式" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="进货商" prop="partnerName">
<el-input v-model="localOrderData.partnerName" placeholder="请选择进货商" :disabled="isReadonly" @click.native="!isReadonly && $emit('select-partner')">
<el-button slot="append" icon="el-icon-search" @click.native="!isReadonly && $emit('select-partner')" :disabled="isReadonly"></el-button>
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="进货商类型" prop="level">
<el-select v-model="localOrderData.level" placeholder="选择后带入" disabled>
<el-option v-for="dict in partnerLevelOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="进货商联系人" prop="partnerUserName">
<el-input v-model="localOrderData.partnerUserName" placeholder="请输入进货商联系人" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="Email" prop="partnerEmail">
<el-input v-model="localOrderData.partnerEmail" placeholder="请输入Email" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系方式" prop="partnerPhone">
<el-input v-model="localOrderData.partnerPhone" placeholder="请输入联系方式" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="收货地址" prop="notifierAddress">
<el-input v-model="localOrderData.notifierAddress" placeholder="请输入收货地址" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="收货人" prop="notifier">
<el-input v-model="localOrderData.notifier" placeholder="请输入收货人" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="Email" prop="notifierEmail">
<el-input v-model="localOrderData.notifierEmail" placeholder="请输入Email" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系方式" prop="notifierPhone">
<el-input v-model="localOrderData.notifierPhone" placeholder="请输入联系方式" :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="付款方式" prop="paymentMethod">
<el-select v-model="localOrderData.paymentMethod" placeholder="请选择付款方式" @change="handlePaymentMethodChange" :disabled="isReadonly">
<el-option v-for="item in paymentMethodOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="付款比例" prop="paymentRatio">
<el-input-number v-model="localOrderData.paymentRatio" :min="0" :max="100" placeholder="请输入付款比例" @change="updatePaymentDescription" :disabled="isReadonly"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="付款条件" prop="paymentDescription">
<el-input v-model="localOrderData.paymentDescription" type="textarea" :rows="3" readonly :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="其他特别说明" prop="remark">
<el-input v-model="localOrderData.remark" placeholder="请输入其他特别说明" :disabled="isReadonly"/>
</el-form-item>
</el-col>
</el-row>
</template>
<script>
import { getDicts } from "@/api/system/dict/data";
export default {
name: "OrderInfo",
props: {
orderData: {
type: Object,
required: true
},
layout: {
type: String,
default: 'page', // 'drawer', 'dialog', 'page'
},
isReadonly: {
type: Boolean,
default: false
}
},
data() {
return {
localOrderData: {},
bgOptions: [],
industryOptions: [],
currencyOptions: [],
companyDeliveryOptions: [],
partnerLevelOptions: [],
paymentMethodOptions: [],
};
},
watch: {
orderData: {
handler(newValue) {
this.localOrderData = newValue;
// orderData
if (newValue.bgProperty) {
this.handleBgChange(newValue.bgProperty, true);
}
if (newValue.orderChannel) {
this.handleChannelChange(newValue.orderChannel, true);
}
},
immediate: true,
deep: true
},
localOrderData: {
handler(newValue) {
this.$emit('update:orderData', newValue);
},
deep: true
}
},
created() {
this.getDicts("bg_type").then(response => { this.bgOptions = response.data; });
this.getDicts("currency_type").then(response => { this.currencyOptions = response.data; });
this.getDicts("company_delivery").then(response => { this.companyDeliveryOptions = response.data; });
this.getDicts("identify_level").then(response => { this.partnerLevelOptions = response.data; });
},
methods: {
getDicts,
handleBgChange(value, isInitialLoad = false) {
if (!isInitialLoad) {
this.localOrderData.industryType = null;
}
const dictType = value === 'YYS' ? 'bg_yys' : 'bg_hysy';
return this.getDicts(dictType).then(response => {
this.industryOptions = response.data;
});
},
handleChannelChange(value, isInitialLoad = false) {
if (!isInitialLoad) {
this.localOrderData.supplier = value === '1' ? '广州佳都技术有限公司' : '紫光汇智信息技术有限公司';
this.localOrderData.paymentMethod = null;
this.localOrderData.paymentRatio = 0;
this.localOrderData.paymentDescription = null;
}
if (value === '1') { //
this.paymentMethodOptions = [
{ label: '全款支付,无需预付款', value: '1-1' },
{ label: '全款支付,需单独备货生产,预付订单总货款百分比', value: '1-2' }
];
} else if (value === '2') { //
this.paymentMethodOptions = [
{ label: '全款支付', value: '2-1' },
{ label: '全款支付,需单独备货生产,预付订单总货款百分比', value: '2-2' },
{ label: '商业汇票支付,预付订单总货款百分比', value: '2-3' }
];
} else {
this.paymentMethodOptions = [];
}
},
handlePaymentMethodChange(value) {
const descriptionTemplates = {
'1-2': '总代预付{ratio}%订单金额作为备货押金后开始备货生产备货完成供货商发起付款通知后总代需1个月内支付尾款完成提货否则备货押金不予退还。',
'2-2': '进货商预付{ratio}%订单金额作为备货押金后开始备货生产备货完成供货商发起付款通知后进货商需3个工作日内付全部剩余款项即可享受订单约定的现金折扣。',
'2-3': '进货商预付{ratio}%订单金额作为备货押金后开始备货生产备货完成供货商发起付款通知后供货商需在1个月内提交剩余款项额度的商业汇票完成提货否则备货押金不予退还。'
};
let description = '';
let paymentRatio = 0;
switch (value) {
case '1-1':
description = '备货完成供货商发起付款通知后,总代按照订单金额支付全款。';
paymentRatio = 100;
break;
case '1-2':
paymentRatio = 30;
description = descriptionTemplates['1-2'].replace('{ratio}', paymentRatio);
break;
case '2-1':
description = '备货完成供货商发起付款通知后进货商需3个工作日内付订单全部款项即可享受订单约定的现金折扣。';
paymentRatio = 100;
break;
case '2-2':
paymentRatio = 30;
description = descriptionTemplates['2-2'].replace('{ratio}', paymentRatio);
break;
case '2-3':
paymentRatio = 30;
description = descriptionTemplates['2-3'].replace('{ratio}', paymentRatio);
break;
}
this.localOrderData.paymentDescription = description;
this.localOrderData.paymentRatio = paymentRatio;
},
updatePaymentDescription() {
const paymentMethod = this.localOrderData.paymentMethod;
const ratio = this.localOrderData.paymentRatio;
const descriptionTemplates = {
'1-2': '总代预付{ratio}%订单金额作为备货押金后开始备货生产备货完成供货商发起付款通知后总代需1个月内支付尾款完成提货否则备货押金不予退还。',
'2-2': '进货商预付{ratio}%订单金额作为备货押金后开始备货生产备货完成供货商发起付款通知后进货商需3个工作日内付全部剩余款项即可享受订单约定的现金折扣。',
'2-3': '进货商预付{ratio}%订单金额作为备货押金后开始备货生产备货完成供货商发起付款通知后供货商需在1个月内提交剩余款项额度的商业汇票完成提货否则备货押金不予退还。'
};
if (descriptionTemplates[paymentMethod]) {
this.localOrderData.paymentDescription = descriptionTemplates[paymentMethod].replace('{ratio}', ratio);
}
},
}
};
</script>
<style scoped>
.el-select, .el-date-picker, .el-input-number {
width: 100%;
}
</style>

View File

@ -105,6 +105,39 @@ export const constantRoutes = [
// 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [
{
path: '/inventory',
component: Layout,
redirect: 'noRedirect',
name: 'Inventory',
meta: {
title: '库存管理',
icon: 'inventory'
},
children: [
{
path: 'execution',
component: () => import('@/views/inventory/execution/index'),
name: 'Execution',
meta: { title: '订单执行跟踪', icon: 'execution' },
permissions: ['inventory:execution:list']
}
]
},
{
path: '/inventory/execution',
component: Layout,
hidden: true,
permissions: ['inventory:execution:edit'],
children: [
{
path: 'edit/:id(\\d+)',
component: () => import('@/views/inventory/execution/edit'),
name: 'ExecutionEdit',
meta: { title: '订单执行编辑', activeMenu: '/inventory/execution' }
}
]
},
{
path: '/system/user-auth',
component: Layout,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff