feat(project):重构项目管理模块并新增订单管理功能
- 移除项目表单内联代码,改为独立的 ProjectForm 组件- 引入 ProjectDetailDrawer 组件用于展示项目详情- 移除旧的项目编辑对话框及相关逻辑 - 新增订单管理页面,支持查询、新增、编辑、删除订单 - 实现订单列表分页及多条件筛选功能 - 添加订单导出功能 - 实现项目详情抽屉在订单模块中的复用 -优化项目查询逻辑,移除冗余的地区与行业选项处理- 更新项目表单交互方式,通过抽屉和独立表单组件进行操作dev_1.0.0
parent
51d24b5dec
commit
dbacc884be
|
|
@ -0,0 +1,53 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询订单管理列表
|
||||
export function listOrder(query) {
|
||||
return request({
|
||||
url: '/project/order/vue/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询订单管理详细信息
|
||||
export function getOrder(id) {
|
||||
return request({
|
||||
url: '/project/order/vue/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增订单管理
|
||||
export function addOrder(data) {
|
||||
return request({
|
||||
url: '/project/order/vue',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改订单管理
|
||||
export function updateOrder(data) {
|
||||
return request({
|
||||
url: '/project/order/vue',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除订单管理
|
||||
export function delOrder(id) {
|
||||
return request({
|
||||
url: '/project/order/vue/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 导出订单管理
|
||||
export function exportOrder(query) {
|
||||
return request({
|
||||
url: '/project/order/vue/export',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,577 @@
|
|||
<template>
|
||||
<div class="product-config">
|
||||
<div class="section-title">配置信息</div>
|
||||
|
||||
<!-- 软件产品 -->
|
||||
<div class="product-section">
|
||||
<div class="add-btn-div">
|
||||
<h3>软件产品</h3>
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="addProduct('software')" :disabled="isActionDisabled">添加</el-button>
|
||||
</div>
|
||||
<el-table :data="softwareList" border style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="产品编码" width="120" prop="productBomCode">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productBomCode" readonly size="small" @click.native="!isActionDisabled && selectProduct('software', scope.$index)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产品型号" width="150" prop="model">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.model" readonly size="small" @click.native="!isActionDisabled && selectProduct('software', scope.$index)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="描述" width="250" prop="productDesc">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productDesc" type="textarea" :rows="2" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="100" prop="quantity">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.quantity" type="number" :min="0" size="small" @input="calculateRow(scope.row)" style="width: 100%;" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="目录单价(¥)" width="120" prop="cataloguePrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.cataloguePriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="指导折扣(%)" width="100" prop="guidanceDiscount">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.guidanceDiscountFormat" readonly size="small">
|
||||
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="折扣(%)" width="100" prop="discount">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.discountFormat" size="small" @blur="handleDiscountChange(scope.row)" style="width: 100%;" :readonly="readonly" :disabled="disabled">
|
||||
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价(¥)" width="120" prop="price">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.priceFormat" size="small" @blur="handlePriceChange(scope.row)" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总价(¥)" width="120" prop="allPrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.allPriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="目录总价(¥)" width="130" prop="catalogueAllPrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.catalogueAllPriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="税率(%)" width="100" prop="taxRate">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.taxRate" type="number" :min="0" :max="100" size="small" style="width: 100%;" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" width="150" prop="remark">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.remark" size="small" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" fixed="right" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="deleteProduct('software', scope.$index)" style="color: #F56C6C;" :disabled="isActionDisabled">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 硬件产品 -->
|
||||
<div class="product-section">
|
||||
<div class="add-btn-div">
|
||||
<h3>硬件产品</h3>
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="addProduct('hardware')" :disabled="isActionDisabled">添加</el-button>
|
||||
</div>
|
||||
<el-table :data="hardwareList" border style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="产品编码" width="120" prop="productBomCode">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productBomCode" readonly size="small" @click.native="!isActionDisabled && selectProduct('hardware', scope.$index)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产品型号" width="150" prop="model">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.model" readonly size="small" @click.native="!isActionDisabled && selectProduct('hardware', scope.$index)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="描述" width="250" prop="productDesc">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productDesc" type="textarea" :rows="2" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="100" prop="quantity">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.quantity" type="number" :min="0" size="small" @input="calculateRow(scope.row)" style="width: 100%;" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="目录单价(¥)" width="120" prop="cataloguePrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.cataloguePriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="指导折扣(%)" width="100" prop="guidanceDiscount">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.guidanceDiscountFormat" readonly size="small">
|
||||
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="折扣(%)" width="100" prop="discount">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.discountFormat" size="small" @blur="handleDiscountChange(scope.row)" style="width: 100%;" :readonly="readonly" :disabled="disabled">
|
||||
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价(¥)" width="120" prop="price">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.priceFormat" size="small" @blur="handlePriceChange(scope.row)" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总价(¥)" width="120" prop="allPrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.allPriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="目录总价(¥)" width="130" prop="catalogueAllPrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.catalogueAllPriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="税率(%)" width="100" prop="taxRate">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.taxRate" type="number" :min="0" :max="100" size="small" style="width: 100%;" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" width="150" prop="remark">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.remark" size="small" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" fixed="right" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="deleteProduct('hardware', scope.$index)" style="color: #F56C6C;" :disabled="isActionDisabled">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 服务产品 -->
|
||||
<div class="product-section">
|
||||
<div class="add-btn-div">
|
||||
<h3>服务产品</h3>
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="addProduct('maintenance')" :disabled="isActionDisabled">添加</el-button>
|
||||
</div>
|
||||
<el-table :data="maintenanceList" border style="width: 100%">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="产品编码" width="120" prop="productBomCode">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productBomCode" readonly size="small" @click.native="!isActionDisabled && selectProduct('maintenance', scope.$index)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产品型号" width="150" prop="model">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.model" readonly size="small" @click.native="!isActionDisabled && selectProduct('maintenance', scope.$index)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="描述" width="250" prop="productDesc">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productDesc" type="textarea" :rows="2" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="100" prop="quantity">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.quantity" type="number" :min="0" size="small" @input="calculateRow(scope.row)" style="width: 100%;" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="目录单价(¥)" width="120" prop="cataloguePrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.cataloguePriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="指导折扣(%)" width="100" prop="guidanceDiscount">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.guidanceDiscountFormat" readonly size="small">
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="折扣(%)" width="100" prop="discount">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.discountFormat" size="small" @blur="handleDiscountChange(scope.row)" style="width: 100%;" :readonly="readonly" :disabled="disabled">
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价(¥)" width="120" prop="price">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.priceFormat" size="small" @blur="handlePriceChange(scope.row)" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总价(¥)" width="120" prop="allPrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.allPriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="目录总价(¥)" width="130" prop="catalogueAllPrice">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.catalogueAllPriceFormat" readonly size="small"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="税率(%)" width="100" prop="taxRate">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.taxRate" type="number" :min="0" :max="100" size="small" style="width: 100%;" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" width="150" prop="remark">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.remark" size="small" :readonly="readonly" :disabled="disabled"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" fixed="right" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="deleteProduct('maintenance', scope.$index)" style="color: #F56C6C;" :disabled="isActionDisabled">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 产品选择对话框 -->
|
||||
<select-product
|
||||
:visible.sync="selectProductVisible"
|
||||
:product-type="currentProductType"
|
||||
@product-selected="handleProductSelected"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectProduct from '@/views/system/product/selectProduct.vue';
|
||||
|
||||
export default {
|
||||
name: 'ProductConfig',
|
||||
components: {
|
||||
SelectProduct
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
softwareProjectProductInfoList: [],
|
||||
hardwareProjectProductInfoList: [],
|
||||
maintenanceProjectProductInfoList: []
|
||||
})
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
softwareList: [],
|
||||
hardwareList: [],
|
||||
maintenanceList: [],
|
||||
selectProductVisible: false,
|
||||
currentProductType: '1', // 1:软件 2:硬件 11,22,99:服务
|
||||
currentEditType: '', // software, hardware, maintenance
|
||||
currentEditIndex: -1
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isActionDisabled() {
|
||||
return this.disabled || this.readonly;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (val) {
|
||||
this.initData(val);
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initData(data) {
|
||||
// 初始化软件产品
|
||||
this.softwareList = (data.softwareProjectProductInfoList || []).map(item => this.formatProduct(item));
|
||||
// 初始化硬件产品
|
||||
this.hardwareList = (data.hardwareProjectProductInfoList || []).map(item => this.formatProduct(item));
|
||||
// 初始化服务产品
|
||||
this.maintenanceList = (data.maintenanceProjectProductInfoList || []).map(item => this.formatProduct(item));
|
||||
},
|
||||
formatProduct(item) {
|
||||
return {
|
||||
...item,
|
||||
quantity: item.quantity || 0,
|
||||
taxRate: item.taxRate || 13,
|
||||
cataloguePriceFormat: this.formatAmount(item.cataloguePrice),
|
||||
guidanceDiscountFormat: item.guidanceDiscount ? this.preciseCurrencyRound(item.guidanceDiscount * 100, 2) : '',
|
||||
discountFormat: item.discount ? this.preciseCurrencyRound(item.discount * 100, 2) : '',
|
||||
priceFormat: this.formatAmount(item.price),
|
||||
allPriceFormat: this.formatAmount(item.allPrice),
|
||||
catalogueAllPriceFormat: this.formatAmount(item.catalogueAllPrice)
|
||||
};
|
||||
},
|
||||
addProduct(type) {
|
||||
const newProduct = {
|
||||
id: null,
|
||||
productBomCode: '',
|
||||
model: '',
|
||||
productDesc: '',
|
||||
quantity: 0,
|
||||
cataloguePrice: 0,
|
||||
cataloguePriceFormat: '',
|
||||
guidanceDiscount: 0,
|
||||
guidanceDiscountFormat: '',
|
||||
discount: 0,
|
||||
discountFormat: '',
|
||||
price: 0,
|
||||
priceFormat: '',
|
||||
allPrice: 0,
|
||||
allPriceFormat: '',
|
||||
catalogueAllPrice: 0,
|
||||
catalogueAllPriceFormat: '',
|
||||
taxRate: 13,
|
||||
remark: ''
|
||||
};
|
||||
|
||||
this.calculateRow(newProduct);
|
||||
|
||||
if (type === 'software') {
|
||||
this.softwareList.push(newProduct);
|
||||
} else if (type === 'hardware') {
|
||||
this.hardwareList.push(newProduct);
|
||||
} else if (type === 'maintenance') {
|
||||
this.maintenanceList.push(newProduct);
|
||||
}
|
||||
|
||||
this.emitChange();
|
||||
},
|
||||
deleteProduct(type, index) {
|
||||
this.$confirm('是否确认删除该产品?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
if (type === 'software') {
|
||||
this.softwareList.splice(index, 1);
|
||||
} else if (type === 'hardware') {
|
||||
this.hardwareList.splice(index, 1);
|
||||
} else if (type === 'maintenance') {
|
||||
this.maintenanceList.splice(index, 1);
|
||||
}
|
||||
this.emitChange();
|
||||
this.$message.success('删除成功');
|
||||
}).catch(() => {});
|
||||
},
|
||||
selectProduct(type, index) {
|
||||
this.currentEditType = type;
|
||||
this.currentEditIndex = index;
|
||||
|
||||
// 设置产品类型
|
||||
if (type === 'software') {
|
||||
this.currentProductType = '1';
|
||||
} else if (type === 'hardware') {
|
||||
this.currentProductType = '2';
|
||||
} else if (type === 'maintenance') {
|
||||
this.currentProductType = '11,22,99';
|
||||
}
|
||||
|
||||
this.selectProductVisible = true;
|
||||
},
|
||||
handleProductSelected(product) {
|
||||
let list = [];
|
||||
if (this.currentEditType === 'software') {
|
||||
list = this.softwareList;
|
||||
} else if (this.currentEditType === 'hardware') {
|
||||
list = this.hardwareList;
|
||||
} else if (this.currentEditType === 'maintenance') {
|
||||
list = this.maintenanceList;
|
||||
}
|
||||
|
||||
const row = list[this.currentEditIndex];
|
||||
row.productBomCode = product.productCode;
|
||||
row.model = product.model;
|
||||
row.productDesc = product.description;
|
||||
row.cataloguePrice = product.cataloguePrice;
|
||||
row.cataloguePriceFormat = this.formatAmount(product.cataloguePrice);
|
||||
row.guidanceDiscount = product.guidanceDiscount;
|
||||
row.guidanceDiscountFormat = product.guidanceDiscount ? this.preciseCurrencyRound(product.guidanceDiscount * 100, 2) : '';
|
||||
row.discount = product.guidanceDiscount || 0;
|
||||
row.discountFormat = product.guidanceDiscount ? this.preciseCurrencyRound(product.guidanceDiscount * 100, 2) : '';
|
||||
|
||||
this.calculateRow(row);
|
||||
this.emitChange();
|
||||
},
|
||||
handleDiscountChange(row) {
|
||||
// 限制折扣输入在0-100之间
|
||||
let value = parseFloat(row.discountFormat);
|
||||
if (isNaN(value)) {
|
||||
value = 0;
|
||||
} else if (value < 0) {
|
||||
value = 0;
|
||||
} else if (value > 100) {
|
||||
value = 100;
|
||||
}
|
||||
row.discountFormat = value;
|
||||
this.calculateRow(row);
|
||||
},
|
||||
handlePriceChange(row) {
|
||||
// 从格式化的字符串中解析价格
|
||||
let price = parseFloat(String(row.priceFormat).replace(/,/g, ''));
|
||||
if (isNaN(price)) {
|
||||
price = 0;
|
||||
}
|
||||
row.price = this.preciseCurrencyRound(price, 2);
|
||||
row.priceFormat = this.formatAmount(row.price);
|
||||
|
||||
// 如果目录单价存在且不为0,则重新计算折扣
|
||||
if (row.cataloguePrice && row.cataloguePrice > 0) {
|
||||
const discount = row.price / row.cataloguePrice;
|
||||
row.discount = this.preciseCurrencyRound(discount, 4); // 精度为4位
|
||||
row.discountFormat = this.preciseCurrencyRound(discount * 100, 2); // 显示为百分比,保留2位小数
|
||||
} else {
|
||||
// 如果目录单价为0,则折扣也为0
|
||||
row.discount = 0;
|
||||
row.discountFormat = 0;
|
||||
}
|
||||
|
||||
// 重新计算总价和目录总价
|
||||
row.allPrice = this.preciseCurrencyRound(row.price * row.quantity, 2);
|
||||
row.allPriceFormat = this.formatAmount(row.allPrice);
|
||||
row.catalogueAllPrice = this.preciseCurrencyRound(row.cataloguePrice * row.quantity, 2);
|
||||
row.catalogueAllPriceFormat = this.formatAmount(row.catalogueAllPrice);
|
||||
|
||||
this.emitChange();
|
||||
},
|
||||
calculateRow(row) {
|
||||
if (this.isActionDisabled){
|
||||
return;
|
||||
}
|
||||
// 计算单价 = 目录单价 * 折扣
|
||||
const discount = row.discountFormat ? row.discountFormat / 100 : 0;
|
||||
row.discount = this.preciseCurrencyRound(discount, 4);
|
||||
row.price = this.preciseCurrencyRound(row.cataloguePrice * discount, 2);
|
||||
row.priceFormat = this.formatAmount(row.price);
|
||||
|
||||
// 计算总价 = 单价 * 数量
|
||||
row.allPrice = this.preciseCurrencyRound(row.price * row.quantity, 2);
|
||||
row.allPriceFormat = this.formatAmount(row.allPrice);
|
||||
|
||||
// 计算目录总价 = 目录单价 * 数量
|
||||
row.catalogueAllPrice = this.preciseCurrencyRound(row.cataloguePrice * row.quantity, 2);
|
||||
row.catalogueAllPriceFormat = this.formatAmount(row.catalogueAllPrice);
|
||||
|
||||
this.emitChange();
|
||||
},
|
||||
formatAmount(value) {
|
||||
if (value === null || value === undefined || value === '') return '';
|
||||
return Number(value).toLocaleString('en-US', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
},
|
||||
preciseCurrencyRound(value, decimals = 2) {
|
||||
return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
|
||||
},
|
||||
emitChange() {
|
||||
const data = {
|
||||
softwareProjectProductInfoList: this.softwareList.map(item => ({
|
||||
...item,
|
||||
cataloguePriceFormat: undefined,
|
||||
guidanceDiscountFormat: undefined,
|
||||
discountFormat: undefined,
|
||||
priceFormat: undefined,
|
||||
allPriceFormat: undefined,
|
||||
catalogueAllPriceFormat: undefined
|
||||
})),
|
||||
hardwareProjectProductInfoList: this.hardwareList.map(item => ({
|
||||
...item,
|
||||
cataloguePriceFormat: undefined,
|
||||
guidanceDiscountFormat: undefined,
|
||||
discountFormat: undefined,
|
||||
priceFormat: undefined,
|
||||
allPriceFormat: undefined,
|
||||
catalogueAllPriceFormat: undefined
|
||||
})),
|
||||
maintenanceProjectProductInfoList: this.maintenanceList.map(item => ({
|
||||
...item,
|
||||
cataloguePriceFormat: undefined,
|
||||
guidanceDiscountFormat: undefined,
|
||||
discountFormat: undefined,
|
||||
priceFormat: undefined,
|
||||
allPriceFormat: undefined,
|
||||
catalogueAllPriceFormat: undefined
|
||||
}))
|
||||
};
|
||||
this.$emit('input', data);
|
||||
this.$emit('change', data);
|
||||
},
|
||||
getData() {
|
||||
return {
|
||||
softwareProjectProductInfoList: this.softwareList,
|
||||
hardwareProjectProductInfoList: this.hardwareList,
|
||||
maintenanceProjectProductInfoList: this.maintenanceList
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.product-config {
|
||||
margin-top: 20px;
|
||||
|
||||
.section-title {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
color: #0075ff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.product-section {
|
||||
margin-bottom: 30px;
|
||||
|
||||
.add-btn-div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-table {
|
||||
font-size: 12px;
|
||||
|
||||
.el-input__inner,
|
||||
.el-textarea__inner {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-input-number {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,470 @@
|
|||
<template>
|
||||
<el-drawer
|
||||
title="项目详情"
|
||||
:visible.sync="localVisible"
|
||||
direction="rtl"
|
||||
size="70%"
|
||||
@close="handleClose"
|
||||
:with-header="true"
|
||||
>
|
||||
<div class="drawer-container">
|
||||
<el-form ref="form" :model="form" label-width="120px">
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="项目信息" name="projectInfo">
|
||||
<div class="tab-content">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目编号" prop="projectCode">
|
||||
<el-input v-model="form.projectCode" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="form.projectName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="BG" prop="bgProperty">
|
||||
<el-select v-model="form.bgProperty" :disabled="true" style="width: 100%;">
|
||||
<el-option
|
||||
v-for="dict in dict.type.bg_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="行业" prop="industryType">
|
||||
<el-select v-model="form.industryType" :disabled="true" style="width: 100%;">
|
||||
<el-option
|
||||
v-for="item in industryOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="代表处" prop="agentName">
|
||||
<el-input v-model="form.agentName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="项目阶段" prop="projectStage">
|
||||
<el-select v-model="form.projectStage" :disabled="true" style="width: 100%;">
|
||||
<el-option
|
||||
v-for="dict in dict.type.project_stage"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="项目把握度" prop="projectGraspDegree">
|
||||
<el-select v-model="form.projectGraspDegree" :disabled="true" style="width: 100%;">
|
||||
<el-option label="A" value="A" />
|
||||
<el-option label="B" value="B" />
|
||||
<el-option label="C" value="C" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="汇智负责人" prop="hzSupportUserName">
|
||||
<el-input v-model="form.hzSupportUserName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最终客户" prop="customerName">
|
||||
<el-input v-model="form.customerName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="客户联系人" prop="customerUserName">
|
||||
<el-input v-model="form.customerUserName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最终客户 TEL" prop="customerPhone">
|
||||
<el-input v-model="form.customerPhone" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="运作方" prop="operateInstitution">
|
||||
<el-select v-model="form.operateInstitution" :disabled="true" style="width: 100%;">
|
||||
<el-option
|
||||
v-for="dict in dict.type.operate_institution"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="新华三联系人" prop="h3cPerson">
|
||||
<el-input v-model="form.h3cPerson" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="新华三TEL" prop="h3cPhone">
|
||||
<el-input v-model="form.h3cPhone" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商" prop="partnerName">
|
||||
<el-input v-model="form.partnerName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商联系人" prop="partnerUserName">
|
||||
<el-input v-model="form.partnerUserName" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商 TEL" prop="contactWay">
|
||||
<el-input v-model="form.contactWay" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计金额(元)" prop="estimatedAmount">
|
||||
<el-input v-model="form.estimatedAmount" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计下单时间" prop="estimatedOrderTime">
|
||||
<el-date-picker clearable
|
||||
v-model="form.estimatedOrderTime"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 100%;"
|
||||
readonly>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="POC测试" prop="poc">
|
||||
<el-select v-model="form.poc" :disabled="true" style="width: 100%;">
|
||||
<el-option label="是" value="1" />
|
||||
<el-option label="否" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="是否国产" prop="countryProduct">
|
||||
<el-select v-model="form.countryProduct" :disabled="true" style="width: 100%;">
|
||||
<el-option label="是" value="1" />
|
||||
<el-option label="否" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="竞争对手" >
|
||||
<el-input :value="form.competitor" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="关键技术问题" prop="keyProblem">
|
||||
<el-input v-model="form.keyProblem" type="textarea" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目简述" prop="projectDesc">
|
||||
<el-input v-model="form.projectDesc" type="textarea" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="服务器配置" prop="serverConfiguration">
|
||||
<el-input v-model="form.serverConfiguration" type="textarea" readonly />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="配置信息" name="productConfig">
|
||||
<div class="tab-content">
|
||||
<product-config :value="form.productConfig" :readonly="true" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="工作进度" name="workProgress">
|
||||
<div class="tab-content">
|
||||
<el-table :data="form.projectWorkProgressList" border>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="更新内容" prop="workContent" />
|
||||
<el-table-column label="更新人员" prop="userName" width="120" align="center" />
|
||||
<el-table-column label="更新时间" prop="workTime" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.workTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="POC 记录" name="pocRecord" v-if="form.poc === '1'">
|
||||
<div class="tab-content">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="服务器配置" prop="projectPocInfo.serverConfig">
|
||||
<el-input v-model="form.projectPocInfo.serverConfig" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="云桌面版本" prop="projectPocInfo.vdiVersion">
|
||||
<el-input v-model="form.projectPocInfo.vdiVersion" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="配置终端" prop="projectPocInfo.terminalConfig">
|
||||
<el-input v-model="form.projectPocInfo.terminalConfig" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="操作系统" prop="projectPocInfo.operateSystem">
|
||||
<el-input v-model="form.projectPocInfo.operateSystem" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="H3C接口人" prop="projectPocInfo.h3cPerson">
|
||||
<el-input v-model="form.projectPocInfo.h3cPerson" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="H3C TEL" prop="projectPocInfo.h3cPhone">
|
||||
<el-input v-model="form.projectPocInfo.h3cPhone" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="汇智接口人" prop="projectPocInfo.hzInterfacePerson">
|
||||
<el-input v-model="form.projectPocInfo.hzInterfacePerson" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="汇智 TEL" prop="projectPocInfo.hzInterfacePhone">
|
||||
<el-input v-model="form.projectPocInfo.hzInterfacePhone" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="研发接口人" prop="projectPocInfo.processPerson">
|
||||
<el-input v-model="form.projectPocInfo.processPerson" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="研发 TEL" prop="projectPocInfo.processPhone">
|
||||
<el-input v-model="form.projectPocInfo.processPhone" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="现场接口人" prop="projectPocInfo.handlePerson">
|
||||
<el-input v-model="form.projectPocInfo.handlePerson" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="现场 TEL" prop="projectPocInfo.handlePhone">
|
||||
<el-input v-model="form.projectPocInfo.handlePhone" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="启动时间" prop="projectPocInfo.startDate">
|
||||
<el-date-picker v-model="form.projectPocInfo.startDate" type="date" readonly style="width:100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计完成时间" prop="projectPocInfo.planFinishTime">
|
||||
<el-date-picker v-model="form.projectPocInfo.planFinishTime" type="date" readonly style="width:100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="实际完成时间" prop="projectPocInfo.realFinishTime">
|
||||
<el-date-picker v-model="form.projectPocInfo.realFinishTime" type="date" readonly style="width:100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<h4 class="form-header">测试进展</h4>
|
||||
<el-table :data="form.projectPocInfo.projectPocInfoDetailList" border>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="测试进展" prop="testProgress" />
|
||||
<el-table-column label="更新人员" prop="createByName" width="120" align="center" />
|
||||
<el-table-column label="更新时间" prop="createTime" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="操作日志" name="operationLog">
|
||||
<div class="tab-content">
|
||||
<el-table :data="form.projectOperateLogList" border>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="操作人员" prop="operateUserName" width="120" align="center" />
|
||||
<el-table-column label="操作内容" prop="operateLog" />
|
||||
<el-table-column label="操作时间" prop="operateTime" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.operateTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getProject } from "@/api/project/info";
|
||||
import ProductConfig from "./ProductConfig.vue";
|
||||
|
||||
export default {
|
||||
name: "ProjectDetailDrawer",
|
||||
components: { ProductConfig },
|
||||
dicts: ['bg_type', 'bg_yys', 'bg_hysy', 'project_stage', 'operate_institution'],
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
projectId: {
|
||||
type: [Number, String],
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
productConfig: {},
|
||||
projectWorkProgressList: [],
|
||||
projectOperateLogList: [],
|
||||
projectPocInfo: {
|
||||
projectPocInfoDetailList: []
|
||||
}
|
||||
},
|
||||
activeTab: 'projectInfo',
|
||||
localVisible: this.visible,
|
||||
industryOptions: [],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
this.localVisible = val;
|
||||
if (val && this.projectId) {
|
||||
this.getDetails();
|
||||
}
|
||||
},
|
||||
projectId(val) {
|
||||
if (val && this.localVisible) {
|
||||
this.getDetails();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetails() {
|
||||
getProject(this.projectId).then(response => {
|
||||
const projectData = response.data.project;
|
||||
|
||||
// Initialize nested objects to avoid "cannot read property of undefined"
|
||||
projectData.productConfig = {
|
||||
softwareProjectProductInfoList: projectData.softwareProjectProductInfoList || [],
|
||||
hardwareProjectProductInfoList: projectData.hardwareProjectProductInfoList || [],
|
||||
maintenanceProjectProductInfoList: projectData.maintenanceProjectProductInfoList || []
|
||||
};
|
||||
projectData.projectWorkProgressList = projectData.projectWorkProgressList || [];
|
||||
projectData.projectOperateLogList = projectData.projectOperateLogList || [];
|
||||
projectData.projectPocInfo = projectData.projectPocInfo || { projectPocInfoDetailList: [] };
|
||||
projectData.projectPocInfo.projectPocInfoDetailList = projectData.projectPocInfo.projectPocInfoDetailList || [];
|
||||
|
||||
this.form = projectData;
|
||||
this.setupIndustryOptions();
|
||||
});
|
||||
},
|
||||
setupIndustryOptions() {
|
||||
if (this.form.bgProperty === 'YYS') {
|
||||
this.industryOptions = this.dict.type.bg_yys;
|
||||
} else if (this.form.bgProperty) {
|
||||
this.industryOptions = this.dict.type.bg_hysy;
|
||||
} else {
|
||||
this.industryOptions = [];
|
||||
}
|
||||
},
|
||||
handleClose() {
|
||||
this.form = {
|
||||
productConfig: {},
|
||||
projectWorkProgressList: [],
|
||||
projectOperateLogList: [],
|
||||
projectPocInfo: {
|
||||
projectPocInfoDetailList: []
|
||||
}
|
||||
};
|
||||
this.activeTab = 'projectInfo';
|
||||
this.$emit("update:visible", false);
|
||||
},
|
||||
// A simple parseTime function placeholder if not globally available
|
||||
parseTime(time, pattern) {
|
||||
if (time === undefined || time === null) {
|
||||
return "";
|
||||
}
|
||||
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}';
|
||||
let date;
|
||||
if (typeof time === 'object') {
|
||||
date = time;
|
||||
} else {
|
||||
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
|
||||
time = parseInt(time);
|
||||
}
|
||||
if ((typeof time === 'number') && (time.toString().length === 10)) {
|
||||
time = time * 1000;
|
||||
}
|
||||
date = new Date(time);
|
||||
}
|
||||
const formatObj = {
|
||||
y: date.getFullYear(),
|
||||
m: date.getMonth() + 1,
|
||||
d: date.getDate(),
|
||||
h: date.getHours(),
|
||||
i: date.getMinutes(),
|
||||
s: date.getSeconds(),
|
||||
a: date.getDay()
|
||||
};
|
||||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||
let value = formatObj[key];
|
||||
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
|
||||
if (result.length > 0 && value < 10) {
|
||||
value = '0' + value;
|
||||
}
|
||||
return value || 0;
|
||||
});
|
||||
return time_str;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.drawer-container {
|
||||
padding: 0 20px;
|
||||
height: 100%;
|
||||
}
|
||||
.tab-content {
|
||||
height: calc(100vh - 120px); /* Adjust based on header height */
|
||||
overflow-y: auto;
|
||||
padding: 15px;
|
||||
}
|
||||
.el-drawer__header {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,748 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- 添加或修改项目管理对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="localVisible" width="80%" append-to-body :close-on-click-modal="false" @close="cancel">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="项目信息" name="projectInfo">
|
||||
<div style="max-height: 60vh; overflow-y: auto; padding: 15px;">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目编号" prop="projectCode">
|
||||
<el-input v-model="form.projectCode" placeholder="保存后自动生成" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="form.projectName" placeholder="请输入项目名称" maxlength="40" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="BG" prop="bgProperty">
|
||||
<el-select v-model="form.bgProperty" placeholder="请选择BG" @change="handleBgChange" style="width: 100%;" :disabled="isFormDisabled">
|
||||
<el-option
|
||||
v-for="dict in dict.type.bg_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="行业" prop="industryType">
|
||||
<el-select v-model="form.industryType" placeholder="请选择行业" style="width: 100%;" :disabled="isFormDisabled">
|
||||
<el-option
|
||||
v-for="item in industryOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="代表处" prop="agentName">
|
||||
<el-input v-model="form.agentName" placeholder="请选择代表处" readonly :disabled="isFormDisabled" @click.native="!isFormDisabled && openSelectAgent()" />
|
||||
<input type="hidden" v-model="form.agentCode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="项目阶段" prop="projectStage">
|
||||
<el-select v-model="form.projectStage" placeholder="请选择项目阶段" style="width: 100%;" :disabled="isFormDisabled">
|
||||
<el-option
|
||||
v-for="dict in dict.type.project_stage"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="项目把握度" prop="projectGraspDegree">
|
||||
<el-select v-model="form.projectGraspDegree" placeholder="请选择项目把握度" style="width: 100%;" :disabled="isFormDisabled">
|
||||
<el-option label="A" value="A" />
|
||||
<el-option label="B" value="B" />
|
||||
<el-option label="C" value="C" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="汇智负责人" prop="hzSupportUserName">
|
||||
<el-input v-model="form.hzSupportUserName" placeholder="请选择汇智负责人" readonly :disabled="isFormDisabled" @click.native="!isFormDisabled && openSelectPeople()" />
|
||||
<input type="hidden" v-model="form.hzSupportUser" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最终客户" prop="customerName">
|
||||
<el-input v-model="form.customerName" placeholder="请选择最终客户" readonly :disabled="isFormDisabled" @click.native="!isFormDisabled && openSelectCustomer()" />
|
||||
<input type="hidden" v-model="form.customerCode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="客户联系人" prop="customerUserName">
|
||||
<el-input v-model="form.customerUserName" placeholder="请输入客户联系人" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最终客户 TEL" prop="customerPhone">
|
||||
<el-input v-model="form.customerPhone" placeholder="请输入最终客户电话" maxlength="11" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="运作方" prop="operateInstitution">
|
||||
<el-select v-model="form.operateInstitution" placeholder="请选择运作方" @change="handleOperateInstitutionChange" style="width: 100%;" :disabled="isFormDisabled">
|
||||
<el-option
|
||||
v-for="dict in dict.type.operate_institution"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="新华三联系人" prop="h3cPerson">
|
||||
<el-input v-model="form.h3cPerson" placeholder="请输入新华三联系人" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="新华三TEL" prop="h3cPhone">
|
||||
<el-input v-model="form.h3cPhone" placeholder="请输入新华三电话" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商" prop="partnerName">
|
||||
<el-input v-model="form.partnerName" placeholder="请选择进货商" readonly :disabled="isFormDisabled" @click.native="!isFormDisabled && openSelectPartner()" />
|
||||
<input type="hidden" v-model="form.partnerCode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商联系人" prop="partnerUserName">
|
||||
<el-input v-model="form.partnerUserName" placeholder="请输入进货商联系人" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商 TEL" prop="contactWay">
|
||||
<el-input v-model="form.contactWay" placeholder="请输入进货商电话" maxlength="11" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计金额(元)" prop="estimatedAmount">
|
||||
<el-input v-model="form.estimatedAmount" placeholder="请输入预计金额" @blur="formatEstimatedAmount" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计下单时间" prop="estimatedOrderTime">
|
||||
<el-date-picker clearable
|
||||
v-model="form.estimatedOrderTime"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="请选择预计下单时间"
|
||||
style="width: 100%;"
|
||||
:disabled="isFormDisabled">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="POC测试" prop="poc">
|
||||
<el-select v-model="form.poc" placeholder="请选择POC" style="width: 100%;" :disabled="isFormDisabled">
|
||||
<el-option label="是" value="1" />
|
||||
<el-option label="否" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="是否国产" prop="countryProduct">
|
||||
<el-select v-model="form.countryProduct" placeholder="请选择" style="width: 100%;" :disabled="isFormDisabled">
|
||||
<el-option label="是" value="1" />
|
||||
<el-option label="否" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="竞争对手" >
|
||||
<div :disabled="isFormDisabled">
|
||||
<el-checkbox-group v-model="form.competitorList" :disabled="isFormDisabled">
|
||||
<el-checkbox label="华为" value="华为"></el-checkbox>
|
||||
<el-checkbox label="锐捷" value="锐捷"></el-checkbox>
|
||||
<el-checkbox label="深信服" value="深信服"></el-checkbox>
|
||||
<el-checkbox label="中兴" value="中兴"></el-checkbox>
|
||||
<el-checkbox label="噢易云" value="噢易云"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<el-input
|
||||
v-model="form.otherCompetitor"
|
||||
placeholder="其他竞争对手"
|
||||
style="width: 400px;"
|
||||
@click.native.stop
|
||||
@mousedown.native.stop
|
||||
:disabled="isFormDisabled"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="关键技术问题" prop="keyProblem">
|
||||
<el-input v-model="form.keyProblem" type="textarea" placeholder="请输入关键技术问题" maxlength="500" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目简述" prop="projectDesc">
|
||||
<el-input v-model="form.projectDesc" type="textarea" placeholder="请输入项目简述" maxlength="500" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
<el-form-item label="服务器配置" prop="serverConfiguration">
|
||||
<el-input v-model="form.serverConfiguration" type="textarea" placeholder="请输入服务器配置" maxlength="500" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="配置信息" name="productConfig">
|
||||
<div style="max-height: 60vh; overflow-y: auto; padding: 15px;">
|
||||
<!-- 产品配置信息 -->
|
||||
<product-config v-model="form.productConfig" ref="productConfig" :disabled="isFormDisabled" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="工作进度" name="workProgress">
|
||||
<div style="max-height: 60vh; overflow-y: auto; padding: 15px;">
|
||||
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAddWorkLog" class="mb8" :disabled="isFormDisabled">添加</el-button>
|
||||
<el-table :data="form.projectWorkProgressList">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="更新内容">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.workContent" type="textarea" :rows="2" :disabled="!!scope.row.id || isFormDisabled" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="更新人员" prop="userName" width="120" align="center" />
|
||||
<el-table-column label="更新时间" prop="workTime" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.workTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="POC 记录" name="pocRecord" v-if="form.poc === '1'">
|
||||
<div style="max-height: 60vh; overflow-y: auto; padding: 15px;">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="服务器配置" prop="projectPocInfo.serverConfig">
|
||||
<el-input v-model="form.projectPocInfo.serverConfig" placeholder="请输入服务器配置" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="云桌面版本" prop="projectPocInfo.vdiVersion">
|
||||
<el-input v-model="form.projectPocInfo.vdiVersion" placeholder="请输入云桌面版本" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="配置终端" prop="projectPocInfo.terminalConfig">
|
||||
<el-input v-model="form.projectPocInfo.terminalConfig" placeholder="请输入配置终端" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="操作系统" prop="projectPocInfo.operateSystem">
|
||||
<el-input v-model="form.projectPocInfo.operateSystem" placeholder="请输入操作系统" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="H3C接口人" prop="projectPocInfo.h3cPerson">
|
||||
<el-input v-model="form.projectPocInfo.h3cPerson" placeholder="请输入H3C接口人" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="H3C TEL" prop="projectPocInfo.h3cPhone">
|
||||
<el-input v-model="form.projectPocInfo.h3cPhone" placeholder="请输入H3C TEL" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="汇智接口人" prop="projectPocInfo.hzInterfacePerson">
|
||||
<el-input v-model="form.projectPocInfo.hzInterfacePerson" placeholder="请输入汇智接口人" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="汇智 TEL" prop="projectPocInfo.hzInterfacePhone">
|
||||
<el-input v-model="form.projectPocInfo.hzInterfacePhone" placeholder="请输入汇智 TEL" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="研发接口人" prop="projectPocInfo.processPerson">
|
||||
<el-input v-model="form.projectPocInfo.processPerson" placeholder="请输入研发接口人" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="研发 TEL" prop="projectPocInfo.processPhone">
|
||||
<el-input v-model="form.projectPocInfo.processPhone" placeholder="请输入研发 TEL" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="现场接口人" prop="projectPocInfo.handlePerson">
|
||||
<el-input v-model="form.projectPocInfo.handlePerson" placeholder="请输入现场接口人" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="现场 TEL" prop="projectPocInfo.handlePhone">
|
||||
<el-input v-model="form.projectPocInfo.handlePhone" placeholder="请输入现场 TEL" :disabled="isFormDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="启动时间" prop="projectPocInfo.startDate">
|
||||
<el-date-picker v-model="form.projectPocInfo.startDate" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width:100%" :disabled="isFormDisabled"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计完成时间" prop="projectPocInfo.planFinishTime">
|
||||
<el-date-picker v-model="form.projectPocInfo.planFinishTime" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width:100%" :disabled="isFormDisabled"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="实际完成时间" prop="projectPocInfo.realFinishTime">
|
||||
<el-date-picker v-model="form.projectPocInfo.realFinishTime" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width:100%" :disabled="isFormDisabled"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<h4 class="form-header">测试进展</h4>
|
||||
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAddPocDetail" class="mb8" :disabled="isFormDisabled">添加</el-button>
|
||||
<el-table :data="form.projectPocInfo.projectPocInfoDetailList">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="测试进展">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.testProgress" type="textarea" :rows="2" :disabled="isFormDisabled" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="更新人员" prop="createByName" width="120" align="center" />
|
||||
<el-table-column label="更新时间" prop="createTime" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="操作日志" name="operationLog">
|
||||
<div style="max-height: 60vh; overflow-y: auto; padding: 15px;">
|
||||
<el-table :data="form.projectOperateLogList">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="操作人员" prop="operateUserName" width="120" align="center" />
|
||||
<el-table-column label="操作内容" prop="operateLog" />
|
||||
<el-table-column label="操作时间" prop="operateTime" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.operateTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button v-if="!isFormDisabled" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<select-agent :visible.sync="selectAgentVisible" @agent-selected="handleAgentSelected" />
|
||||
<select-customer :visible.sync="selectCustomerVisible" @customer-selected="handleCustomerSelected" />
|
||||
<select-partner :visible.sync="selectPartnerVisible" @partner-selected="handlePartnerSelected" />
|
||||
<select-user :visible.sync="selectUserVisible" @user-selected="handleUserSelected" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getProject, addProject, updateProject } from "@/api/project/info";
|
||||
import { listAreas } from "@/api/system/area";
|
||||
import SelectAgent from "../../system/agent/selectAgent.vue";
|
||||
import SelectCustomer from "../../system/customer/selectCustomer.vue";
|
||||
import SelectPartner from "../../system/partner/selectPartner.vue";
|
||||
import SelectUser from "@/views/system/user/selectUser";
|
||||
import ProductConfig from "./ProductConfig.vue";
|
||||
|
||||
export default {
|
||||
name: "ProjectForm",
|
||||
components: {
|
||||
SelectAgent,
|
||||
SelectCustomer,
|
||||
SelectPartner,
|
||||
SelectUser,
|
||||
ProductConfig,
|
||||
},
|
||||
dicts: ['bg_type', 'bg_yys', 'bg_hysy', 'project_stage', 'operate_institution'],
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
projectId: {
|
||||
type: [Number, String],
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const pocRequiredValidator = (rule, value, callback) => {
|
||||
if (this.form.poc === '1' && !value) {
|
||||
callback(new Error(rule.message));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
title: "",
|
||||
localVisible: this.visible,
|
||||
isFormDisabled: false,
|
||||
activeTab: 'projectInfo',
|
||||
provinceOptions: [],
|
||||
cityOptions: [],
|
||||
industryOptions: [],
|
||||
selectAgentVisible: false,
|
||||
selectCustomerVisible: false,
|
||||
selectPartnerVisible: false,
|
||||
selectUserVisible: false,
|
||||
form: {
|
||||
competitorList: [],
|
||||
otherCompetitor: '',
|
||||
productConfig: {
|
||||
softwareProjectProductInfoList: [],
|
||||
hardwareProjectProductInfoList: [],
|
||||
maintenanceProjectProductInfoList: []
|
||||
},
|
||||
projectWorkProgressList: [],
|
||||
projectOperateLogList: [],
|
||||
projectPocInfo: {
|
||||
projectPocInfoDetailList: []
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
projectName: [
|
||||
{ required: true, message: "项目名称不能为空", trigger: "blur" }
|
||||
],
|
||||
bgProperty: [
|
||||
{ required: true, message: "BG不能为空", trigger: "change" }
|
||||
],
|
||||
industryType: [
|
||||
{ required: true, message: "行业不能为空", trigger: "change" }
|
||||
],
|
||||
agentName: [
|
||||
{ required: true, message: "代表处不能为空", trigger: "change" }
|
||||
],
|
||||
projectStage: [
|
||||
{ required: true, message: "项目阶段不能为空", trigger: "change" }
|
||||
],
|
||||
projectGraspDegree: [
|
||||
{ required: true, message: "项目把握度不能为空", trigger: "change" }
|
||||
],
|
||||
customerName: [
|
||||
{ required: true, message: "最终客户不能为空", trigger: "change" }
|
||||
],
|
||||
operateInstitution: [
|
||||
{ required: true, message: "运作方不能为空", trigger: "change" }
|
||||
],
|
||||
estimatedAmount: [
|
||||
{ required: true, message: "预计金额不能为空", trigger: "blur" }
|
||||
],
|
||||
projectDesc: [
|
||||
{ required: true, message: "项目简述不能为空", trigger: "blur" }
|
||||
],
|
||||
h3cPerson: [
|
||||
{ validator: (rule, value, callback) => {
|
||||
if (this.form.operateInstitution === 'h3c' && !value) {
|
||||
callback(new Error("新华三联系人不能为空"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}, trigger: "blur" }
|
||||
],
|
||||
h3cPhone: [
|
||||
{ validator: (rule, value, callback) => {
|
||||
if (this.form.operateInstitution === 'h3c' && !value) {
|
||||
callback(new Error("新华三TEL不能为空"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}, trigger: "blur" }
|
||||
],
|
||||
'projectPocInfo.serverConfig': [{required: true, validator: pocRequiredValidator, message: "服务器配置不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.vdiVersion': [{required: true, validator: pocRequiredValidator, message: "云桌面版本不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.terminalConfig': [{required: true, validator: pocRequiredValidator, message: "配置终端不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.operateSystem': [{ required: true,validator: pocRequiredValidator, message: "操作系统不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.h3cPerson': [{ required: true,validator: pocRequiredValidator, message: "H3C接口人不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.h3cPhone': [{ required: true,validator: pocRequiredValidator, message: "H3C TEL不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.hzInterfacePerson': [{ required: true,validator: pocRequiredValidator, message: "汇智接口人不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.hzInterfacePhone': [{ required: true,validator: pocRequiredValidator, message: "汇智 TEL不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.processPerson': [{ required: true,validator: pocRequiredValidator, message: "研发接口人不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.processPhone': [{ required: true,validator: pocRequiredValidator, message: "研发 TEL不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.handlePerson': [{ required: true,validator: pocRequiredValidator, message: "现场接口人不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.handlePhone': [{ required: true,validator: pocRequiredValidator, message: "现场 TEL不能为空", trigger: "blur" }],
|
||||
'projectPocInfo.startDate': [{ required: true,validator: pocRequiredValidator, message: "启动时间不能为空", trigger: "change" }],
|
||||
'projectPocInfo.planFinishTime': [{ required: true,validator: pocRequiredValidator, message: "预计完成时间不能为空", trigger: "change" }],
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
this.localVisible = val;
|
||||
if (val) {
|
||||
this.getProvinceList();
|
||||
if (this.projectId) {
|
||||
this.handleUpdate();
|
||||
} else {
|
||||
this.handleAdd();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getProvinceList() {
|
||||
listAreas(0).then(response => {
|
||||
this.provinceOptions = response;
|
||||
});
|
||||
},
|
||||
handleProvinceChange(provinceName) {
|
||||
this.form.city = null;
|
||||
const selectedProvince = this.provinceOptions.find(p => p.n === provinceName);
|
||||
if (selectedProvince) {
|
||||
this.cityOptions = selectedProvince.s;
|
||||
} else {
|
||||
this.cityOptions = [];
|
||||
}
|
||||
},
|
||||
handleBgChange(bgValue) {
|
||||
this.form.industryType = null;
|
||||
if (bgValue === 'YYS') {
|
||||
this.industryOptions = this.dict.type.bg_yys;
|
||||
} else if (bgValue) {
|
||||
this.industryOptions = this.dict.type.bg_hysy;
|
||||
} else {
|
||||
this.industryOptions = [];
|
||||
}
|
||||
},
|
||||
cancel() {
|
||||
this.localVisible = false;
|
||||
this.$emit("update:visible", false);
|
||||
this.reset();
|
||||
},
|
||||
reset() {
|
||||
this.form = {
|
||||
id: null,
|
||||
projectCode: null,
|
||||
projectName: null,
|
||||
bgProperty: null,
|
||||
industryType: null,
|
||||
agentName: null,
|
||||
agentCode: null,
|
||||
projectStage: null,
|
||||
projectGraspDegree: null,
|
||||
hzSupportUserName: null,
|
||||
hzSupportUser: null,
|
||||
customerName: null,
|
||||
customerCode: null,
|
||||
customerUserName: null,
|
||||
customerPhone: null,
|
||||
operateInstitution: null,
|
||||
h3cPerson: null,
|
||||
h3cPhone: null,
|
||||
partnerName: null,
|
||||
partnerCode: null,
|
||||
partnerUserName: null,
|
||||
contactWay: null,
|
||||
estimatedAmount: null,
|
||||
estimatedOrderTime: null,
|
||||
poc: '0',
|
||||
competitorList: [],
|
||||
otherCompetitor: '',
|
||||
countryProduct: null,
|
||||
keyProblem: null,
|
||||
projectDesc: null,
|
||||
serverConfiguration: null,
|
||||
productConfig: {
|
||||
softwareProjectProductInfoList: [],
|
||||
hardwareProjectProductInfoList: [],
|
||||
maintenanceProjectProductInfoList: []
|
||||
},
|
||||
projectWorkProgressList: [],
|
||||
projectOperateLogList: [],
|
||||
projectPocInfo: {
|
||||
projectPocInfoDetailList: []
|
||||
},
|
||||
createAt: null,
|
||||
updatedAt: null
|
||||
};
|
||||
this.activeTab = 'projectInfo';
|
||||
this.isFormDisabled = false;
|
||||
this.cityOptions = [];
|
||||
this.industryOptions = [];
|
||||
this.resetForm("form");
|
||||
},
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.title = "添加项目管理";
|
||||
},
|
||||
handleUpdate() {
|
||||
this.reset();
|
||||
getProject(this.projectId).then(response => {
|
||||
this.form = response.data.project;
|
||||
this.isFormDisabled = !response.data.canUpdate;
|
||||
|
||||
this.$set(this.form, 'otherCompetitor', this.form.otherCompetitor || '');
|
||||
this.$set(this.form, 'competitorList', this.form.competitorList || []);
|
||||
|
||||
if (this.form.competitor) {
|
||||
const allCompetitors = this.form.competitor.split(",");
|
||||
const predefinedCompetitors = ['华为', '锐捷', '深信服', '中兴', '噢易云'];
|
||||
this.$set(this.form, 'otherCompetitor', allCompetitors.filter(c => !predefinedCompetitors.includes(c)).join(','));
|
||||
this.$set(this.form, 'competitorList', allCompetitors.filter(c => predefinedCompetitors.includes(c)));
|
||||
}
|
||||
|
||||
if (this.form.province) {
|
||||
const selectedProvince = this.provinceOptions.find(p => p.n === this.form.province);
|
||||
if (selectedProvince) {
|
||||
this.cityOptions = selectedProvince.s;
|
||||
}
|
||||
}
|
||||
if (this.form.bgProperty) {
|
||||
if (this.form.bgProperty === 'YYS') {
|
||||
this.industryOptions = this.dict.type.bg_yys;
|
||||
} else {
|
||||
this.industryOptions = this.dict.type.bg_hysy;
|
||||
}
|
||||
}
|
||||
|
||||
this.$set(this.form, 'productConfig', {
|
||||
softwareProjectProductInfoList: this.form.softwareProjectProductInfoList || [],
|
||||
hardwareProjectProductInfoList: this.form.hardwareProjectProductInfoList || [],
|
||||
maintenanceProjectProductInfoList: this.form.maintenanceProjectProductInfoList || []
|
||||
});
|
||||
|
||||
this.$set(this.form, 'projectWorkProgressList', this.form.projectWorkProgressList || []);
|
||||
this.$set(this.form, 'projectOperateLogList', this.form.projectOperateLogList || []);
|
||||
this.$set(this.form, 'projectPocInfo', this.form.projectPocInfo || { projectPocInfoDetailList: [] });
|
||||
this.$set(this.form.projectPocInfo, 'projectPocInfoDetailList', this.form.projectPocInfo.projectPocInfoDetailList || []);
|
||||
|
||||
this.title = "修改项目管理";
|
||||
});
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
let finalCompetitorList = [...this.form.competitorList];
|
||||
if (this.form.otherCompetitor) {
|
||||
finalCompetitorList = finalCompetitorList.concat(this.form.otherCompetitor.split(',').map(s => s.trim()).filter(s => s.length > 0));
|
||||
}
|
||||
this.form.competitor = finalCompetitorList.join(',');
|
||||
|
||||
if (this.form.productConfig) {
|
||||
this.form.softwareProjectProductInfoList = this.form.productConfig.softwareProjectProductInfoList || [];
|
||||
this.form.hardwareProjectProductInfoList = this.form.productConfig.hardwareProjectProductInfoList || [];
|
||||
this.form.maintenanceProjectProductInfoList = this.form.productConfig.maintenanceProjectProductInfoList || [];
|
||||
}
|
||||
|
||||
if (this.form.id != null) {
|
||||
updateProject(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.localVisible = false;
|
||||
this.$emit("update:visible", false);
|
||||
this.$emit("success");
|
||||
});
|
||||
} else {
|
||||
addProject(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.localVisible = false;
|
||||
this.$emit("update:visible", false);
|
||||
this.$emit("success");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.$modal.msgError("请检查表单和poc记录必填项");
|
||||
}
|
||||
});
|
||||
},
|
||||
formatEstimatedAmount() {
|
||||
if (this.form.estimatedAmount) {
|
||||
this.form.estimatedAmount = this.form.estimatedAmount.replace(/[^0-9.]/g,'').replace(/(\..*)\./g, '$1');
|
||||
}
|
||||
},
|
||||
handleOperateInstitutionChange(value) {
|
||||
if (value === 'h3c') {
|
||||
this.form.partnerName = '新华三';
|
||||
this.form.partnerCode = null;
|
||||
}
|
||||
if (this.$refs.form) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form.validateField('h3cPerson');
|
||||
this.$refs.form.validateField('h3cPhone');
|
||||
});
|
||||
}
|
||||
},
|
||||
openSelectAgent() {
|
||||
this.selectAgentVisible = true;
|
||||
},
|
||||
handleAgentSelected(agent) {
|
||||
this.form.agentName = agent.agentName;
|
||||
this.form.agentCode = agent.agentCode;
|
||||
this.selectAgentVisible = false;
|
||||
},
|
||||
openSelectCustomer() {
|
||||
this.selectCustomerVisible = true;
|
||||
},
|
||||
handleCustomerSelected(customer) {
|
||||
this.form.customerName = customer.customerName;
|
||||
this.form.customerCode = customer.customerCode;
|
||||
this.form.customerUserName = customer.contactPerson;
|
||||
this.form.customerPhone = customer.contactPhone;
|
||||
this.selectCustomerVisible = false;
|
||||
},
|
||||
openSelectPartner() {
|
||||
this.selectPartnerVisible = true;
|
||||
},
|
||||
handlePartnerSelected(partner) {
|
||||
this.form.partnerName = partner.partnerName;
|
||||
this.form.partnerCode = partner.partnerCode;
|
||||
this.form.partnerUserName = partner.contactPerson;
|
||||
this.form.contactWay = partner.contactPhone;
|
||||
this.selectPartnerVisible = false;
|
||||
},
|
||||
openSelectPeople() {
|
||||
this.selectUserVisible = true;
|
||||
},
|
||||
handleUserSelected(user) {
|
||||
this.form.hzSupportUserName = user.userName;
|
||||
this.form.hzSupportUser = user.userId;
|
||||
this.selectUserVisible = false;
|
||||
},
|
||||
handleAddWorkLog() {
|
||||
if (!this.form.projectWorkProgressList) {
|
||||
this.$set(this.form, 'projectWorkProgressList', []);
|
||||
}
|
||||
this.form.projectWorkProgressList.push({
|
||||
workContent: '',
|
||||
userName: '',
|
||||
workTime: ''
|
||||
});
|
||||
},
|
||||
handleAddPocDetail() {
|
||||
if (!this.form.projectPocInfo.projectPocInfoDetailList) {
|
||||
this.$set(this.form.projectPocInfo, 'projectPocInfoDetailList', []);
|
||||
}
|
||||
this.form.projectPocInfo.projectPocInfoDetailList.push({
|
||||
testProgress: '',
|
||||
createByName: '',
|
||||
createTime: ''
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="BG" prop="bgProperty">
|
||||
<el-select v-model="queryParams.bgProperty" placeholder="请选择BG" clearable @change="handleSearchBgChange">
|
||||
<el-select v-model="queryParams.bgProperty" placeholder="请选择BG" clearable>
|
||||
<el-option
|
||||
v-for="dict in dict.type.bg_type"
|
||||
:key="dict.value"
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
<el-table-column label="项目编号" align="center" prop="projectCode" width="100" />
|
||||
<el-table-column label="项目名称" align="center" prop="projectName" width="300">
|
||||
<template slot-scope="scope">
|
||||
<a @click="viewDetail(scope.row.id)" class="link-type">{{ scope.row.projectName }}</a>
|
||||
<a @click="handleView(scope.row)" class="link-type">{{ scope.row.projectName }}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最终客户" align="center" prop="customerName" width="200" />
|
||||
|
|
@ -226,242 +226,30 @@
|
|||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改项目管理对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body :close-on-click-modal="false">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px" style="max-height: 60vh; overflow-y: auto; padding-right: 20px;">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目编号" prop="projectCode">
|
||||
<el-input v-model="form.projectCode" placeholder="保存后自动生成" readonly />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="form.projectName" placeholder="请输入项目名称" maxlength="40" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="BG" prop="bgProperty">
|
||||
<el-select v-model="form.bgProperty" placeholder="请选择BG" @change="handleBgChange" style="width: 100%;">
|
||||
<el-option
|
||||
v-for="dict in dict.type.bg_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="行业" prop="industryType">
|
||||
<el-select v-model="form.industryType" placeholder="请选择行业" style="width: 100%;">
|
||||
<el-option
|
||||
v-for="item in industryOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="代表处" prop="agentName">
|
||||
<el-input v-model="form.agentName" placeholder="请选择代表处" readonly @click.native="openSelectAgent" />
|
||||
<input type="hidden" v-model="form.agentCode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="项目阶段" prop="projectStage">
|
||||
<el-select v-model="form.projectStage" placeholder="请选择项目阶段" style="width: 100%;">
|
||||
<el-option
|
||||
v-for="dict in dict.type.project_stage"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="项目把握度" prop="projectGraspDegree">
|
||||
<el-select v-model="form.projectGraspDegree" placeholder="请选择项目把握度" style="width: 100%;">
|
||||
<el-option label="A" value="A" />
|
||||
<el-option label="B" value="B" />
|
||||
<el-option label="C" value="C" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="汇智负责人" prop="hzSupportUserName">
|
||||
<el-input v-model="form.hzSupportUserName" placeholder="请选择汇智负责人" readonly @click.native="openSelectPeople" />
|
||||
<input type="hidden" v-model="form.hzSupportUser" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最终客户" prop="customerName">
|
||||
<el-input v-model="form.customerName" placeholder="请选择最终客户" readonly @click.native="openSelectCustomer" />
|
||||
<input type="hidden" v-model="form.customerCode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="客户联系人" prop="customerUserName">
|
||||
<el-input v-model="form.customerUserName" placeholder="请输入客户联系人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最终客户 TEL" prop="customerPhone">
|
||||
<el-input v-model="form.customerPhone" placeholder="请输入最终客户电话" maxlength="11" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="运作方" prop="operateInstitution">
|
||||
<el-select v-model="form.operateInstitution" placeholder="请选择运作方" @change="handleOperateInstitutionChange" style="width: 100%;">
|
||||
<el-option
|
||||
v-for="dict in dict.type.operate_institution"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="新华三联系人" prop="h3cPerson">
|
||||
<el-input v-model="form.h3cPerson" placeholder="请输入新华三联系人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="新华三TEL" prop="h3cPhone">
|
||||
<el-input v-model="form.h3cPhone" placeholder="请输入新华三电话" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商" prop="partnerName">
|
||||
<el-input v-model="form.partnerName" placeholder="请选择进货商" readonly @click.native="openSelectPartner" />
|
||||
<input type="hidden" v-model="form.partnerCode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商联系人" prop="partnerUserName">
|
||||
<el-input v-model="form.partnerUserName" placeholder="请输入进货商联系人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商 TEL" prop="contactWay">
|
||||
<el-input v-model="form.contactWay" placeholder="请输入进货商电话" maxlength="11" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计金额(元)" prop="estimatedAmount">
|
||||
<el-input v-model="form.estimatedAmount" placeholder="请输入预计金额" @blur="formatEstimatedAmount" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计下单时间" prop="estimatedOrderTime">
|
||||
<el-date-picker clearable
|
||||
v-model="form.estimatedOrderTime"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="请选择预计下单时间"
|
||||
style="width: 100%;">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="POC测试" prop="poc">
|
||||
<el-select v-model="form.poc" placeholder="请选择POC" style="width: 100%;">
|
||||
<el-option label="是" value="1" />
|
||||
<el-option label="否" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="是否国产" prop="countryProduct">
|
||||
<el-select v-model="form.countryProduct" placeholder="请选择" style="width: 100%;">
|
||||
<el-option label="是" value="1" />
|
||||
<el-option label="否" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="竞争对手" >
|
||||
<div>
|
||||
<el-checkbox-group v-model="form.competitorList">
|
||||
<el-checkbox label="华为" value="华为"></el-checkbox>
|
||||
<el-checkbox label="锐捷" value="锐捷"></el-checkbox>
|
||||
<el-checkbox label="深信服" value="深信服"></el-checkbox>
|
||||
<el-checkbox label="中兴" value="中兴"></el-checkbox>
|
||||
<el-checkbox label="噢易云" value="噢易云"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<el-input
|
||||
v-model="form.otherCompetitor"
|
||||
placeholder="其他竞争对手"
|
||||
style="width: 400px;"
|
||||
@click.native.stop
|
||||
@mousedown.native.stop
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="关键技术问题" prop="keyProblem">
|
||||
<el-input v-model="form.keyProblem" type="textarea" placeholder="请输入关键技术问题" maxlength="500" />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目简述" prop="projectDesc">
|
||||
<el-input v-model="form.projectDesc" type="textarea" placeholder="请输入项目简述" maxlength="500" />
|
||||
</el-form-item>
|
||||
<el-form-item label="服务器配置" prop="serverConfiguration">
|
||||
<el-input v-model="form.serverConfiguration" type="textarea" placeholder="请输入服务器配置" maxlength="500" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 项目详情抽屉 -->
|
||||
<project-detail-drawer :visible.sync="drawerVisible" :project-id="currentProjectId" />
|
||||
|
||||
<select-agent :visible.sync="selectAgentVisible" @agent-selected="handleAgentSelected" />
|
||||
<select-customer :visible.sync="selectCustomerVisible" @customer-selected="handleCustomerSelected" />
|
||||
<select-partner :visible.sync="selectPartnerVisible" @partner-selected="handlePartnerSelected" />
|
||||
<select-user :visible.sync="selectUserVisible" @user-selected="handleUserSelected" />
|
||||
<!-- 项目表单 -->
|
||||
<project-form
|
||||
:visible.sync="projectFormVisible"
|
||||
:project-id="selectedProjectId"
|
||||
@success="handleFormSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listProject, getProject, delProject, addProject, updateProject, exportProject } from "@/api/project/info";
|
||||
import { listAreas } from "@/api/system/area";
|
||||
import SelectAgent from "../../system/agent/selectAgent.vue";
|
||||
import SelectCustomer from "../../system/customer/selectCustomer.vue";
|
||||
import SelectPartner from "../../system/partner/selectPartner.vue";
|
||||
import SelectUser from "@/views/system/user/selectUser"; // Reusing the existing SelectUser component
|
||||
import { listProject, delProject, exportProject } from "@/api/project/info";
|
||||
import ProjectDetailDrawer from "./ProjectDetailDrawer.vue";
|
||||
import ProjectForm from "./ProjectForm.vue";
|
||||
|
||||
export default {
|
||||
name: "Project",
|
||||
components: {
|
||||
SelectAgent,
|
||||
SelectCustomer,
|
||||
SelectPartner,
|
||||
SelectUser
|
||||
ProjectDetailDrawer,
|
||||
ProjectForm,
|
||||
},
|
||||
dicts: ['bg_type', 'bg_yys', 'bg_hysy', 'project_stage', 'operate_institution'],
|
||||
dicts: ['bg_type', 'bg_yys', 'bg_hysy', 'project_stage'],
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
|
|
@ -478,10 +266,12 @@ export default {
|
|||
total: 0,
|
||||
// 项目管理表格数据
|
||||
projectList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 抽屉可见性
|
||||
drawerVisible: false,
|
||||
currentProjectId: null,
|
||||
// 项目表单可见性
|
||||
projectFormVisible: false,
|
||||
selectedProjectId: null,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
|
|
@ -503,91 +293,10 @@ export default {
|
|||
lastWorkUpdateTimeEnd: null,
|
||||
},
|
||||
dateRange: [],
|
||||
// 省份选项
|
||||
provinceOptions: [],
|
||||
// 城市选项
|
||||
cityOptions: [],
|
||||
// 搜索省份选项
|
||||
searchProvinceOptions: [],
|
||||
// 搜索城市选项
|
||||
searchCityOptions: [],
|
||||
// 行业选项
|
||||
industryOptions: [],
|
||||
// 搜索行业选项
|
||||
searchIndustryOptions: [],
|
||||
// 选择器可见性
|
||||
selectAgentVisible: false,
|
||||
selectCustomerVisible: false,
|
||||
selectPartnerVisible: false,
|
||||
selectUserVisible: false,
|
||||
selectProductVisible: false, // 控制产品选择对话框的可见性
|
||||
currentProductRowIndex: null, // 当前正在编辑的产品行索引
|
||||
currentProductListType: null, // 当前正在编辑的产品列表类型 (software, hardware, maintenance)
|
||||
// 表单参数
|
||||
form: {
|
||||
competitorList: [], // Initialize as array for checkboxes
|
||||
otherCompetitor: null, // For the "其他" competitor input
|
||||
softwareProjectProductInfoList: [],
|
||||
hardwareProjectProductInfoList: [],
|
||||
maintenanceProjectProductInfoList: [],
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
projectName: [
|
||||
{ required: true, message: "项目名称不能为空", trigger: "blur" }
|
||||
],
|
||||
bgProperty: [
|
||||
{ required: true, message: "BG不能为空", trigger: "change" }
|
||||
],
|
||||
industryType: [
|
||||
{ required: true, message: "行业不能为空", trigger: "change" }
|
||||
],
|
||||
agentName: [
|
||||
{ required: true, message: "代表处不能为空", trigger: "change" }
|
||||
],
|
||||
projectStage: [
|
||||
{ required: true, message: "项目阶段不能为空", trigger: "change" }
|
||||
],
|
||||
projectGraspDegree: [
|
||||
{ required: true, message: "项目把握度不能为空", trigger: "change" }
|
||||
],
|
||||
customerName: [
|
||||
{ required: true, message: "最终客户不能为空", trigger: "change" }
|
||||
],
|
||||
operateInstitution: [
|
||||
{ required: true, message: "运作方不能为空", trigger: "change" }
|
||||
],
|
||||
estimatedAmount: [
|
||||
{ required: true, message: "预计金额不能为空", trigger: "blur" }
|
||||
],
|
||||
projectDesc: [
|
||||
{ required: true, message: "项目简述不能为空", trigger: "blur" }
|
||||
],
|
||||
h3cPerson: [
|
||||
{ validator: (rule, value, callback) => {
|
||||
if (this.form.operateInstitution === 'h3c' && !value) {
|
||||
callback(new Error("新华三联系人不能为空"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}, trigger: "blur" }
|
||||
],
|
||||
h3cPhone: [
|
||||
{ validator: (rule, value, callback) => {
|
||||
if (this.form.operateInstitution === 'h3c' && !value) {
|
||||
callback(new Error("新华三TEL不能为空"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}, trigger: "blur" }
|
||||
],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getProvinceList(); // For selectAgent/selectCustomer/selectPartner
|
||||
this.handleSearchBgChange(this.queryParams.bgProperty); // Initialize search industry options
|
||||
},
|
||||
watch: {
|
||||
dateRange(val) {
|
||||
|
|
@ -611,6 +320,22 @@ export default {
|
|||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
searchIndustryOptions() {
|
||||
const yys = this.dict.type.bg_yys || [];
|
||||
const hysy = this.dict.type.bg_hysy || [];
|
||||
const combined = [...yys, ...hysy];
|
||||
|
||||
const uniqueMap = new Map();
|
||||
combined.forEach(item => {
|
||||
if (!uniqueMap.has(item.value)) {
|
||||
uniqueMap.set(item.value, item);
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(uniqueMap.values());
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 查询项目管理列表 */
|
||||
getList() {
|
||||
|
|
@ -621,55 +346,6 @@ export default {
|
|||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 查询省份列表 (for selectAgent/selectCustomer/selectPartner) */
|
||||
getProvinceList() {
|
||||
listAreas(0).then(response => {
|
||||
this.provinceOptions = response;
|
||||
this.searchProvinceOptions = response;
|
||||
});
|
||||
},
|
||||
/** 搜索省份选择改变时 */
|
||||
handleSearchProvinceChange(provinceName) {
|
||||
this.queryParams.city = null;
|
||||
const selectedProvince = this.searchProvinceOptions.find(p => p.n === provinceName);
|
||||
if (selectedProvince) {
|
||||
this.searchCityOptions = selectedProvince.s;
|
||||
} else {
|
||||
this.searchCityOptions = [];
|
||||
}
|
||||
},
|
||||
/** 省份选择改变时 (for add/edit dialog) */
|
||||
handleProvinceChange(provinceName) {
|
||||
this.form.city = null;
|
||||
const selectedProvince = this.provinceOptions.find(p => p.n === provinceName);
|
||||
if (selectedProvince) {
|
||||
this.cityOptions = selectedProvince.s;
|
||||
} else {
|
||||
this.cityOptions = [];
|
||||
}
|
||||
},
|
||||
/** 搜索BG选择改变时 */
|
||||
handleSearchBgChange(bgValue) {
|
||||
this.queryParams.industryType = null;
|
||||
if (bgValue === 'YYS') {
|
||||
this.searchIndustryOptions = this.dict.type.bg_yys;
|
||||
} else if (bgValue) { // Only update if a BG is selected
|
||||
this.searchIndustryOptions = this.dict.type.bg_hysy;
|
||||
} else {
|
||||
this.searchIndustryOptions = []; // Clear if no BG selected
|
||||
}
|
||||
},
|
||||
/** BG选择改变时 (for add/edit dialog) */
|
||||
handleBgChange(bgValue) {
|
||||
this.form.industryType = null;
|
||||
if (bgValue === 'YYS') {
|
||||
this.industryOptions = this.dict.type.bg_yys;
|
||||
} else if (bgValue) { // Only update if a BG is selected
|
||||
this.industryOptions = this.dict.type.bg_hysy;
|
||||
} else {
|
||||
this.industryOptions = []; // Clear if no BG selected
|
||||
}
|
||||
},
|
||||
/** 时间类型选择改变时 */
|
||||
handleTimeTypeChange() {
|
||||
this.dateRange = []; // Clear date range when time type changes
|
||||
|
|
@ -678,52 +354,6 @@ export default {
|
|||
this.queryParams.lastWorkUpdateTimeStart = null;
|
||||
this.queryParams.lastWorkUpdateTimeEnd = null;
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: null,
|
||||
projectCode: null,
|
||||
projectName: null,
|
||||
bgProperty: null,
|
||||
industryType: null,
|
||||
agentName: null,
|
||||
agentCode: null,
|
||||
projectStage: null,
|
||||
projectGraspDegree: null,
|
||||
hzSupportUserName: null,
|
||||
hzSupportUser: null,
|
||||
customerName: null,
|
||||
customerCode: null,
|
||||
customerUserName: null,
|
||||
customerPhone: null,
|
||||
operateInstitution: null,
|
||||
h3cPerson: null,
|
||||
h3cPhone: null,
|
||||
partnerName: null,
|
||||
partnerCode: null,
|
||||
partnerUserName: null,
|
||||
contactWay: null,
|
||||
estimatedAmount: null,
|
||||
estimatedOrderTime: null,
|
||||
poc: '0', // Default to '否'
|
||||
competitorList: [],
|
||||
otherCompetitor: '', // 改为空字符串,确保响应式
|
||||
countryProduct: null,
|
||||
keyProblem: null,
|
||||
projectDesc: null,
|
||||
serverConfiguration: null,
|
||||
createAt: null,
|
||||
updatedAt: null
|
||||
};
|
||||
this.cityOptions = [];
|
||||
this.industryOptions = [];
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
|
|
@ -739,8 +369,6 @@ export default {
|
|||
this.queryParams.lastWorkUpdateTimeStart = null;
|
||||
this.queryParams.lastWorkUpdateTimeEnd = null;
|
||||
this.queryParams.industryType = null; // Clear industry type
|
||||
this.searchIndustryOptions = []; // Clear search industry options
|
||||
this.handleSearchBgChange(this.queryParams.bgProperty); // Re-initialize search industry options based on default BG
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
|
|
@ -751,74 +379,18 @@ export default {
|
|||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加项目管理";
|
||||
this.selectedProjectId = null;
|
||||
this.projectFormVisible = true;
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id || this.ids
|
||||
getProject(id).then(response => {
|
||||
this.form = response.data;
|
||||
|
||||
// 确保 otherCompetitor 和 competitorList 是响应式的
|
||||
this.$set(this.form, 'otherCompetitor', '');
|
||||
this.$set(this.form, 'competitorList', []);
|
||||
|
||||
// Handle competitorList and otherCompetitor
|
||||
if (this.form.competitor) {
|
||||
const allCompetitors = this.form.competitor.split(",");
|
||||
const predefinedCompetitors = ['华为', '锐捷', '深信服', '中兴', '噢易云'];
|
||||
this.$set(this.form, 'otherCompetitor', allCompetitors.filter(c => !predefinedCompetitors.includes(c)).join(','));
|
||||
this.$set(this.form, 'competitorList', allCompetitors.filter(c => predefinedCompetitors.includes(c)));
|
||||
}
|
||||
|
||||
// Populate city options if province is already set
|
||||
if (this.form.province) {
|
||||
const selectedProvince = this.provinceOptions.find(p => p.n === this.form.province);
|
||||
if (selectedProvince) {
|
||||
this.cityOptions = selectedProvince.s;
|
||||
}
|
||||
}
|
||||
// Populate industry options if bgProperty is already set
|
||||
if (this.form.bgProperty) {
|
||||
if (this.form.bgProperty === 'YYS') {
|
||||
this.industryOptions = this.dict.type.bg_yys;
|
||||
} else {
|
||||
this.industryOptions = this.dict.type.bg_hysy;
|
||||
}
|
||||
}
|
||||
this.open = true;
|
||||
this.title = "修改项目管理";
|
||||
});
|
||||
this.selectedProjectId = row.id;
|
||||
this.projectFormVisible = true;
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
// Combine competitorList and otherCompetitor before submitting
|
||||
let finalCompetitorList = [...this.form.competitorList];
|
||||
if (this.form.otherCompetitor) {
|
||||
finalCompetitorList = finalCompetitorList.concat(this.form.otherCompetitor.split(',').map(s => s.trim()).filter(s => s.length > 0));
|
||||
}
|
||||
this.form.competitorList = finalCompetitorList;
|
||||
|
||||
if (this.form.id != null) {
|
||||
updateProject(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addProject(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
/** 表单提交成功 */
|
||||
handleFormSuccess() {
|
||||
this.projectFormVisible = false;
|
||||
this.getList();
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
|
|
@ -850,75 +422,10 @@ export default {
|
|||
}
|
||||
return '';
|
||||
},
|
||||
/** 金额输入框失去焦点时格式化 */
|
||||
formatEstimatedAmount() {
|
||||
if (this.form.estimatedAmount) {
|
||||
this.form.estimatedAmount = this.form.estimatedAmount.replace(/[^0-9.]/g,'').replace(/(\..*)\./g, '$1');
|
||||
}
|
||||
},
|
||||
/** 运作方选择改变时 */
|
||||
handleOperateInstitutionChange(value) {
|
||||
// 当选择新华三时,自动填充进货商为"新华三"
|
||||
if (value === 'h3c') {
|
||||
this.form.partnerName = '新华三';
|
||||
this.form.partnerCode = null;
|
||||
}
|
||||
// 重新验证新华三联系人和新华三TEL字段
|
||||
if (this.$refs.form) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form.validateField('h3cPerson');
|
||||
this.$refs.form.validateField('h3cPhone');
|
||||
});
|
||||
}
|
||||
},
|
||||
/** 打开选择代表处对话框 */
|
||||
openSelectAgent() {
|
||||
this.selectAgentVisible = true;
|
||||
},
|
||||
/** 处理代表处选择 */
|
||||
handleAgentSelected(agent) {
|
||||
this.form.agentName = agent.agentName;
|
||||
this.form.agentCode = agent.agentCode;
|
||||
this.selectAgentVisible = false;
|
||||
},
|
||||
/** 打开选择客户对话框 */
|
||||
openSelectCustomer() {
|
||||
this.selectCustomerVisible = true;
|
||||
},
|
||||
/** 处理客户选择 */
|
||||
handleCustomerSelected(customer) {
|
||||
this.form.customerName = customer.customerName;
|
||||
this.form.customerCode = customer.customerCode;
|
||||
this.form.customerUserName = customer.contactPerson;
|
||||
this.form.customerPhone = customer.contactPhone;
|
||||
this.selectCustomerVisible = false;
|
||||
},
|
||||
/** 打开选择进货商对话框 */
|
||||
openSelectPartner() {
|
||||
this.selectPartnerVisible = true;
|
||||
},
|
||||
/** 处理进货商选择 */
|
||||
handlePartnerSelected(partner) {
|
||||
this.form.partnerName = partner.partnerName;
|
||||
this.form.partnerCode = partner.partnerCode;
|
||||
this.form.partnerUserName = partner.contactPerson;
|
||||
this.form.contactWay = partner.contactPhone;
|
||||
this.selectPartnerVisible = false;
|
||||
},
|
||||
/** 打开选择汇智负责人对话框 */
|
||||
openSelectPeople() {
|
||||
this.selectUserVisible = true;
|
||||
},
|
||||
/** 处理汇智负责人选择 */
|
||||
handleUserSelected(user) {
|
||||
this.form.hzSupportUserName = user.userName;
|
||||
this.form.hzSupportUser = user.userId;
|
||||
this.selectUserVisible = false;
|
||||
},
|
||||
/** 查看项目详情 */
|
||||
viewDetail(id) {
|
||||
// This would typically open a new route or a larger dialog for project details
|
||||
this.$modal.alert("查看项目详情,ID: " + id);
|
||||
handleView(row) {
|
||||
this.currentProjectId = row.id;
|
||||
this.drawerVisible = true;
|
||||
},
|
||||
/** 生成订单 */
|
||||
openOrder(id, canGenerate) {
|
||||
|
|
@ -927,7 +434,6 @@ export default {
|
|||
return;
|
||||
}
|
||||
this.$modal.alert("生成订单,项目ID: " + id);
|
||||
// This would typically open a new route or a larger dialog for order creation
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,495 @@
|
|||
<template>
|
||||
<!-- 添加或修改订单管理对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="internalVisible" width="1400px" append-to-body @close="handleClose">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="基础信息" name="basic">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="form.projectName" placeholder="选择项目后带入" readonly>
|
||||
<el-button slot="append" icon="el-icon-search" @click="handleSelectProject"></el-button>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="版本号" prop="versionCode">
|
||||
<el-input-number v-model="form.versionCode" :min="1" label="版本号"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目编号" prop="projectCode">
|
||||
<el-input v-model="form.projectCode" placeholder="选择项目后带入" readonly/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最终客户" prop="customerName">
|
||||
<el-input v-model="form.customerName" placeholder="选择项目后带入" readonly/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="BG" prop="bgProperty">
|
||||
<el-select v-model="form.bgProperty" placeholder="请选择BG" @change="handleBgChange">
|
||||
<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="form.industryType" placeholder="请先选择BG">
|
||||
<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="form.agentName" placeholder="选择项目后带入" readonly/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="进货商接口人" prop="businessPerson">
|
||||
<el-input v-model="form.businessPerson" placeholder="请输入进货商接口人"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Email" prop="businessEmail">
|
||||
<el-input v-model="form.businessEmail" placeholder="请输入Email"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="联系方式" prop="businessPhone">
|
||||
<el-input v-model="form.businessPhone" placeholder="请输入联系方式"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="合同编号" prop="orderCode">
|
||||
<el-input v-model="form.orderCode" placeholder="自动生成" readonly/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="执行单有效截止时间" prop="orderEndTime">
|
||||
<el-date-picker v-model="form.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="form.currencyType" placeholder="请选择币种">
|
||||
<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 :span="8">
|
||||
<el-form-item label="总代出货金额" prop="shipmentAmount">
|
||||
<el-input v-model="form.shipmentAmount" placeholder="请输入金额"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="要求到货时间" prop="deliveryTime">
|
||||
<el-date-picker clearable size="small" v-model="form.deliveryTime" type="date" value-format="yyyy-MM-dd" placeholder="选择要求到货时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="公司直发" prop="companyDelivery">
|
||||
<el-select v-model="form.companyDelivery" placeholder="请选择">
|
||||
<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="form.orderChannel" placeholder="请选择" @change="handleChannelChange">
|
||||
<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="form.orderChannel == '1'">
|
||||
<el-form-item label="总代" prop="zd">
|
||||
<el-input value="广州佳都技术有限公司" readonly/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="供货商" prop="supplier">
|
||||
<el-input v-model="form.supplier" readonly/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="汇智责任人" prop="dutyName">
|
||||
<el-input v-model="form.dutyName" placeholder="请选择责任人">
|
||||
<el-button slot="append" icon="el-icon-search" @click="handleSelectUser"></el-button>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Email" prop="dutyEmail">
|
||||
<el-input v-model="form.dutyEmail" placeholder="请输入Email"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="联系方式" prop="dutyPhone">
|
||||
<el-input v-model="form.dutyPhone" placeholder="请输入联系方式"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="进货商" prop="partnerName">
|
||||
<el-input v-model="form.partnerName" placeholder="请选择进货商">
|
||||
<el-button slot="append" icon="el-icon-search" @click="handleSelectPartner"></el-button>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="进货商类型" prop="level">
|
||||
<el-select v-model="form.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="form.partnerUserName" placeholder="请输入进货商联系人"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Email" prop="partnerEmail">
|
||||
<el-input v-model="form.partnerEmail" placeholder="请输入Email"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="联系方式" prop="partnerPhone">
|
||||
<el-input v-model="form.partnerPhone" placeholder="请输入联系方式"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="收货地址" prop="notifierAddress">
|
||||
<el-input v-model="form.notifierAddress" placeholder="请输入收货地址"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="收货人" prop="notifier">
|
||||
<el-input v-model="form.notifier" placeholder="请输入收货人"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="Email" prop="notifierEmail">
|
||||
<el-input v-model="form.notifierEmail" placeholder="请输入Email"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="联系方式" prop="notifierPhone">
|
||||
<el-input v-model="form.notifierPhone" placeholder="请输入联系方式"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="付款方式" prop="paymentMethod">
|
||||
<el-select v-model="form.paymentMethod" placeholder="请选择付款方式" @change="handlePaymentMethodChange">
|
||||
<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="12">
|
||||
<el-form-item label="付款比例" prop="paymentRatio">
|
||||
<el-input-number v-model="form.paymentRatio" :min="0" :max="100" placeholder="请输入付款比例" @change="updatePaymentDescription"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="付款条件" prop="paymentDescription">
|
||||
<el-input v-model="form.paymentDescription" type="textarea" :rows="3" readonly/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="其他特别说明" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入其他特别说明"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="配置信息" name="config">
|
||||
<product-config v-model="form" :disabled="!isEdit" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="流转过程" name="flow">
|
||||
<!-- 流转过程 -->
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="备货信息" name="stock">
|
||||
<!-- 备货信息 -->
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="物流信息" name="delivery">
|
||||
<!-- 物流信息 -->
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="合同信息" name="contract">
|
||||
<!-- 合同信息 -->
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getOrder, addOrder, updateOrder } from "@/api/project/order";
|
||||
import { getDicts } from "@/api/system/dict/data";
|
||||
import ProductConfig from '@/views/project/info/ProductConfig.vue';
|
||||
|
||||
export default {
|
||||
name: "OrderDetail",
|
||||
components: {
|
||||
ProductConfig
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
orderId: {
|
||||
type: Number,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 内部可见性控制
|
||||
internalVisible: this.visible,
|
||||
// 当前激活的Tab
|
||||
activeTab: 'basic',
|
||||
// 字典数据
|
||||
bgOptions: [],
|
||||
industryOptions: [],
|
||||
currencyOptions: [],
|
||||
companyDeliveryOptions: [],
|
||||
partnerLevelOptions: [],
|
||||
paymentMethodOptions: [],
|
||||
// 表单校验
|
||||
rules: {
|
||||
projectName: [{ required: true, message: "项目名称不能为空", trigger: "blur" }],
|
||||
versionCode: [{ required: true, message: "版本号不能为空", trigger: "blur" }],
|
||||
projectCode: [{ required: true, message: "项目编号不能为空", trigger: "blur" }],
|
||||
customerName: [{ required: true, message: "最终客户不能为空", trigger: "blur" }],
|
||||
bgProperty: [{ required: true, message: "BG不能为空", trigger: "change" }],
|
||||
industryType: [{ required: true, message: "行业不能为空", trigger: "change" }],
|
||||
agentName: [{ required: true, message: "代表处不能为空", trigger: "blur" }],
|
||||
businessPerson: [{ required: true, message: "进货商接口人不能为空", trigger: "blur" }],
|
||||
businessPhone: [{ required: true, message: "联系方式不能为空", trigger: "blur" }],
|
||||
currencyType: [{ required: true, message: "币种不能为空", trigger: "change" }],
|
||||
shipmentAmount: [{ required: true, message: "总代出货金额不能为空", trigger: "blur" }],
|
||||
deliveryTime: [{ required: true, message: "要求到货时间不能为空", trigger: "blur" }],
|
||||
orderChannel: [{ required: true, message: "下单通路不能为空", trigger: "change" }],
|
||||
supplier: [{ required: true, message: "供货商不能为空", trigger: "blur" }],
|
||||
dutyPhone: [{ required: true, message: "联系方式不能为空", trigger: "blur" }],
|
||||
partnerName: [{ required: true, message: "进货商不能为空", trigger: "blur" }],
|
||||
level: [{ required: true, message: "进货商类型不能为空", trigger: "change" }],
|
||||
partnerPhone: [{ required: true, message: "联系方式不能为空", trigger: "blur" }],
|
||||
notifierAddress: [{ required: true, message: "收货地址不能为空", trigger: "blur" }],
|
||||
notifierPhone: [{ required: true, message: "联系方式不能为空", trigger: "blur" }],
|
||||
paymentMethod: [{ required: true, message: "付款方式不能为空", trigger: "change" }],
|
||||
paymentRatio: [{ required: true, message: "付款比例不能为空", trigger: "blur" }],
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isEdit() {
|
||||
return this.orderId != null;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
this.internalVisible = val;
|
||||
if (val) {
|
||||
this.handleOpen();
|
||||
}
|
||||
}
|
||||
},
|
||||
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: {
|
||||
// 打开弹窗处理
|
||||
handleOpen() {
|
||||
this.reset();
|
||||
if (this.isEdit) {
|
||||
getOrder(this.orderId).then(response => {
|
||||
this.form = response.data;
|
||||
// 手动触发联动
|
||||
this.handleBgChange(this.form.bgProperty);
|
||||
this.handleChannelChange(this.form.orderChannel);
|
||||
this.handlePaymentMethodChange(this.form.paymentMethod);
|
||||
});
|
||||
} else {
|
||||
// 设置新增时的默认值
|
||||
this.form.dutyName = this.$store.state.user.name;
|
||||
this.form.dutyEmail = this.$store.state.user.email;
|
||||
this.form.dutyPhone = this.$store.state.user.phonenumber;
|
||||
}
|
||||
},
|
||||
// 关闭弹窗
|
||||
handleClose() {
|
||||
this.$emit('update:visible', false);
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.handleClose();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: null,
|
||||
projectName: null,
|
||||
versionCode: 1,
|
||||
projectCode: null,
|
||||
customerName: null,
|
||||
bgProperty: null,
|
||||
industryType: null,
|
||||
agentName: null,
|
||||
businessPerson: null,
|
||||
businessEmail: null,
|
||||
businessPhone: null,
|
||||
orderCode: null,
|
||||
orderEndTime: null,
|
||||
currencyType: null,
|
||||
shipmentAmount: null,
|
||||
deliveryTime: null,
|
||||
companyDelivery: '0',
|
||||
orderChannel: null,
|
||||
supplier: null,
|
||||
dutyName: null,
|
||||
dutyEmail: null,
|
||||
dutyPhone: null,
|
||||
partnerName: null,
|
||||
level: null,
|
||||
partnerUserName: null,
|
||||
partnerEmail: null,
|
||||
partnerPhone: null,
|
||||
notifierAddress: null,
|
||||
notifier: null,
|
||||
notifierEmail: null,
|
||||
notifierPhone: null,
|
||||
paymentMethod: null,
|
||||
paymentRatio: 0,
|
||||
paymentDescription: null,
|
||||
remark: null,
|
||||
softwareProjectProductInfoList: [],
|
||||
hardwareProjectProductInfoList: [],
|
||||
maintenanceProjectProductInfoList: []
|
||||
};
|
||||
this.activeTab = 'basic';
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
const action = this.isEdit ? updateOrder : addOrder;
|
||||
action(this.form).then(response => {
|
||||
this.msgSuccess(this.isEdit ? "修改成功" : "新增成功");
|
||||
this.handleClose();
|
||||
this.$emit('success');
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
/** BG改变事件 */
|
||||
handleBgChange(value) {
|
||||
this.form.industryType = null;
|
||||
const dictType = value === 'YYS' ? 'bg_yys' : 'bg_hysy';
|
||||
getDicts(dictType).then(response => {
|
||||
this.industryOptions = response.data;
|
||||
});
|
||||
},
|
||||
/** 下单通路改变事件 */
|
||||
handleChannelChange(value) {
|
||||
this.form.supplier = value === '1' ? '广州佳都技术有限公司' : '紫光汇智信息技术有限公司';
|
||||
this.form.paymentMethod = null;
|
||||
this.form.paymentRatio = 0;
|
||||
this.form.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.form.paymentDescription = description;
|
||||
this.form.paymentRatio = paymentRatio;
|
||||
},
|
||||
/** 更新付款条件描述 */
|
||||
updatePaymentDescription() {
|
||||
const paymentMethod = this.form.paymentMethod;
|
||||
const ratio = this.form.paymentRatio;
|
||||
const descriptionTemplates = {
|
||||
'1-2': '总代预付{ratio}%订单金额作为备货押金后开始备货生产,备货完成供货商发起付款通知后,总代需1个月内支付尾款完成提货,否则备货押金不予退还。',
|
||||
'2-2': '进货商预付{ratio}%订单金额作为备货押金后开始备货生产,备货完成供货商发起付款通知后,进货商需3个工作日内付全部剩余款项,即可享受订单约定的现金折扣。',
|
||||
'2-3': '进货商预付{ratio}%订单金额作为备货押金后开始备货生产,备货完成供货商发起付款通知后,供货商需在1个月内提交剩余款项额度的商业汇票完成提货,否则备货押金不予退还。'
|
||||
};
|
||||
if (descriptionTemplates[paymentMethod]) {
|
||||
this.form.paymentDescription = descriptionTemplates[paymentMethod].replace('{ratio}', ratio);
|
||||
}
|
||||
},
|
||||
/** 选择项目按钮操作 */
|
||||
handleSelectProject() {
|
||||
this.msgWarning("选择项目功能待实现");
|
||||
},
|
||||
/** 选择用户按钮操作 */
|
||||
handleSelectUser() {
|
||||
this.msgWarning("选择用户功能待实现");
|
||||
},
|
||||
/** 选择合作伙伴按钮操作 */
|
||||
handleSelectPartner() {
|
||||
this.msgWarning("选择合作伙伴功能待实现");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索表单 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="项目编号" prop="projectCode">
|
||||
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="合同编号" prop="orderCode">
|
||||
<el-input v-model="queryParams.orderCode" placeholder="请输入合同编号" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="最终客户" prop="customerName">
|
||||
<el-input v-model="queryParams.customerName" placeholder="请输入最终客户" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单状态" prop="orderStatus">
|
||||
<el-select v-model="queryParams.orderStatus" placeholder="请选择订单状态" clearable size="small">
|
||||
<el-option v-for="dict in orderStatusOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="代表处" prop="agentName">
|
||||
<el-input v-model="queryParams.agentName" placeholder="请输入代表处" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="汇智负责人" prop="dutyName">
|
||||
<el-input v-model="queryParams.dutyName" placeholder="请输入项目负责人" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="进货商" prop="partnerName">
|
||||
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间选择">
|
||||
<el-select v-model="queryParams.timeType" size="small" style="width: 140px">
|
||||
<el-option label="到货时间" value="deliveryTime"></el-option>
|
||||
<el-option label="下单时间" value="estimatedOrderTime"></el-option>
|
||||
<el-option label="执行单截止时间" value="orderEndTime"></el-option>
|
||||
</el-select>
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['project:order:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['project:order:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['project:order:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="orderList" @selection-change="handleSelectionChange" @sort-change="handleSortChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="项目编号" align="center" prop="projectCode" width="100" />
|
||||
<el-table-column label="项目名称" align="center" prop="projectName" width="300" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<a @click="handleViewProject(scope.row)" class="link-type">{{ scope.row.projectName }}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="合同编号" align="center" prop="orderCode" width="200" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<span class="link-type" @click="handleUpdate(scope.row)">{{ scope.row.orderCode }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最终客户" align="center" prop="customerName" width="200" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="金额(¥)" align="center" prop="shipmentAmount" width="100" sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<span>{{
|
||||
formatAmount(scope.row.shipmentAmount)
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单状态" align="center" prop="orderStatus" width="100">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.order_status" :value="scope.row.orderStatus"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="代表处" align="center" prop="agentName" width="100" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="汇智负责人" align="center" prop="dutyName" width="100"/>
|
||||
<el-table-column label="物流状态" align="center" width="100" />
|
||||
<el-table-column label="进货商" align="center" prop="partnerName" width="200" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="到货时间" align="center" prop="deliveryTime" width="200" sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.deliveryTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="下单时间" align="center" prop="estimatedOrderTime" width="200" sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.estimatedOrderTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="执行单截止时间" align="center" prop="orderEndTime" width="200" sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.orderEndTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.showLog">
|
||||
<el-button size="mini" type="text" icon="el-icon-view" @click="viewApproveLog(scope.row)">审批历史</el-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:order:edit']">编辑</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['project:order:remove']">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
||||
|
||||
<!-- 订单详情对话框 -->
|
||||
<order-detail :visible.sync="open" :title="title" :order-id="currentOrderId" @success="getList"></order-detail>
|
||||
|
||||
<!-- 项目详情抽屉 -->
|
||||
<project-detail-drawer :visible.sync="projectDrawerVisible" :project-id="currentProjectId" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOrder, delOrder, exportOrder } from "@/api/project/order";
|
||||
import OrderDetail from './OrderDetail.vue';
|
||||
import ProjectDetailDrawer from '../info/ProjectDetailDrawer.vue';
|
||||
|
||||
export default {
|
||||
name: "Order",
|
||||
components: {
|
||||
OrderDetail,
|
||||
ProjectDetailDrawer
|
||||
},
|
||||
dicts: ['order_status'],
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 订单管理表格数据
|
||||
orderList: [],
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// --- 对话框控制 ---
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 当前操作的订单ID
|
||||
currentOrderId: null,
|
||||
// --- 抽屉控制 ---
|
||||
projectDrawerVisible: false,
|
||||
currentProjectId: null,
|
||||
// --- 查询参数 ---
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
projectCode: null,
|
||||
projectName: null,
|
||||
orderCode: null,
|
||||
customerName: null,
|
||||
orderStatus: null,
|
||||
agentName: null,
|
||||
dutyName: null,
|
||||
partnerName: null,
|
||||
timeType: 'deliveryTime',
|
||||
params: {}
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询订单管理列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
let query = { ...this.queryParams };
|
||||
query.params = {};
|
||||
|
||||
if (this.dateRange && this.dateRange.length === 2) {
|
||||
const timeType = this.queryParams.timeType;
|
||||
const beginKey = `begin${timeType.charAt(0).toUpperCase() + timeType.slice(1)}`;
|
||||
const endKey = `end${timeType.charAt(0).toUpperCase() + timeType.slice(1)}`;
|
||||
query.params[beginKey] = this.dateRange[0];
|
||||
query.params[endKey] = this.dateRange[1];
|
||||
}
|
||||
|
||||
delete query.timeType;
|
||||
|
||||
listOrder(query).then(response => {
|
||||
this.orderList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.single = selection.length!==1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.currentOrderId = null;
|
||||
this.open = true;
|
||||
this.title = "添加订单";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.currentOrderId = row.id || this.ids[0];
|
||||
this.open = true;
|
||||
this.title = "修改订单";
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const ids = row.id || this.ids;
|
||||
this.$confirm('是否确认删除订单管理编号为"' + ids + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return delOrder(ids);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams;
|
||||
this.$confirm('是否确认导出所有订单管理数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.exportLoading = true;
|
||||
return exportOrder(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
this.exportLoading = false;
|
||||
})
|
||||
},
|
||||
/** 排序触发事件 */
|
||||
handleSortChange(column) {
|
||||
this.queryParams.orderByColumn = column.prop;
|
||||
if (column.order === 'ascending') {
|
||||
this.queryParams.isAsc = 'asc';
|
||||
} else if (column.order === 'descending') {
|
||||
this.queryParams.isAsc = 'desc';
|
||||
} else {
|
||||
this.queryParams.isAsc = null;
|
||||
this.queryParams.orderByColumn = null;
|
||||
}
|
||||
this.getList();
|
||||
},
|
||||
/** 格式化金额 */
|
||||
formatAmount(value) {
|
||||
if (value === null || value === undefined || value === '') return '0.00';
|
||||
return Number(value).toLocaleString('en-US', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
},
|
||||
/** 查看项目详情 */
|
||||
handleViewProject(row) {
|
||||
this.currentProjectId = row.projectId;
|
||||
this.projectDrawerVisible = true;
|
||||
},
|
||||
/** 查看审批历史 */
|
||||
viewApproveLog(row) {
|
||||
// this.$router.push({ path: '/project/order/approveLog/' + row.id });
|
||||
this.msgWarning("查看审批历史功能待实现");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<el-dialog title="选择产品" :visible.sync="visible" width="1000px" append-to-body @close="handleClose">
|
||||
<el-dialog title="选择产品" :visible.sync="visible" width="60%" append-to-body @close="handleClose">
|
||||
<div style="max-height: 60vh; overflow-y: auto;">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
|
||||
<el-form-item label="产品编码" prop="productCode">
|
||||
<el-input
|
||||
|
|
@ -38,6 +39,7 @@
|
|||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">取 消</el-button>
|
||||
|
|
@ -74,19 +76,19 @@ export default {
|
|||
pageSize: 10,
|
||||
productCode: null,
|
||||
model: null,
|
||||
productType: this.productType // Pass productType to query params
|
||||
type: this.productType // Pass productType to query params
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (val) {
|
||||
this.queryParams.productType = this.productType; // Update productType when dialog opens
|
||||
this.queryParams.type = this.productType; // Update productType when dialog opens
|
||||
this.getList();
|
||||
}
|
||||
},
|
||||
productType(val) {
|
||||
this.queryParams.productType = val;
|
||||
this.queryParams.type = val;
|
||||
if (this.visible) {
|
||||
this.getList();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue