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>
|
||||||
<el-form-item label="BG" prop="bgProperty">
|
<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
|
<el-option
|
||||||
v-for="dict in dict.type.bg_type"
|
v-for="dict in dict.type.bg_type"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
|
|
@ -147,7 +147,7 @@
|
||||||
<el-table-column label="项目编号" align="center" prop="projectCode" width="100" />
|
<el-table-column label="项目编号" align="center" prop="projectCode" width="100" />
|
||||||
<el-table-column label="项目名称" align="center" prop="projectName" width="300">
|
<el-table-column label="项目名称" align="center" prop="projectName" width="300">
|
||||||
<template slot-scope="scope">
|
<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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="最终客户" align="center" prop="customerName" width="200" />
|
<el-table-column label="最终客户" align="center" prop="customerName" width="200" />
|
||||||
|
|
@ -226,242 +226,30 @@
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 添加或修改项目管理对话框 -->
|
<!-- 项目详情抽屉 -->
|
||||||
<el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body :close-on-click-modal="false">
|
<project-detail-drawer :visible.sync="drawerVisible" :project-id="currentProjectId" />
|
||||||
<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>
|
|
||||||
|
|
||||||
<select-agent :visible.sync="selectAgentVisible" @agent-selected="handleAgentSelected" />
|
<!-- 项目表单 -->
|
||||||
<select-customer :visible.sync="selectCustomerVisible" @customer-selected="handleCustomerSelected" />
|
<project-form
|
||||||
<select-partner :visible.sync="selectPartnerVisible" @partner-selected="handlePartnerSelected" />
|
:visible.sync="projectFormVisible"
|
||||||
<select-user :visible.sync="selectUserVisible" @user-selected="handleUserSelected" />
|
:project-id="selectedProjectId"
|
||||||
|
@success="handleFormSuccess"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listProject, getProject, delProject, addProject, updateProject, exportProject } from "@/api/project/info";
|
import { listProject, delProject, exportProject } from "@/api/project/info";
|
||||||
import { listAreas } from "@/api/system/area";
|
import ProjectDetailDrawer from "./ProjectDetailDrawer.vue";
|
||||||
import SelectAgent from "../../system/agent/selectAgent.vue";
|
import ProjectForm from "./ProjectForm.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
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Project",
|
name: "Project",
|
||||||
components: {
|
components: {
|
||||||
SelectAgent,
|
ProjectDetailDrawer,
|
||||||
SelectCustomer,
|
ProjectForm,
|
||||||
SelectPartner,
|
|
||||||
SelectUser
|
|
||||||
},
|
},
|
||||||
dicts: ['bg_type', 'bg_yys', 'bg_hysy', 'project_stage', 'operate_institution'],
|
dicts: ['bg_type', 'bg_yys', 'bg_hysy', 'project_stage'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 遮罩层
|
// 遮罩层
|
||||||
|
|
@ -478,10 +266,12 @@ export default {
|
||||||
total: 0,
|
total: 0,
|
||||||
// 项目管理表格数据
|
// 项目管理表格数据
|
||||||
projectList: [],
|
projectList: [],
|
||||||
// 弹出层标题
|
// 抽屉可见性
|
||||||
title: "",
|
drawerVisible: false,
|
||||||
// 是否显示弹出层
|
currentProjectId: null,
|
||||||
open: false,
|
// 项目表单可见性
|
||||||
|
projectFormVisible: false,
|
||||||
|
selectedProjectId: null,
|
||||||
// 查询参数
|
// 查询参数
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
|
|
@ -503,91 +293,10 @@ export default {
|
||||||
lastWorkUpdateTimeEnd: null,
|
lastWorkUpdateTimeEnd: null,
|
||||||
},
|
},
|
||||||
dateRange: [],
|
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() {
|
created() {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.getProvinceList(); // For selectAgent/selectCustomer/selectPartner
|
|
||||||
this.handleSearchBgChange(this.queryParams.bgProperty); // Initialize search industry options
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
dateRange(val) {
|
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: {
|
methods: {
|
||||||
/** 查询项目管理列表 */
|
/** 查询项目管理列表 */
|
||||||
getList() {
|
getList() {
|
||||||
|
|
@ -621,55 +346,6 @@ export default {
|
||||||
this.loading = false;
|
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() {
|
handleTimeTypeChange() {
|
||||||
this.dateRange = []; // Clear date range when time type changes
|
this.dateRange = []; // Clear date range when time type changes
|
||||||
|
|
@ -678,52 +354,6 @@ export default {
|
||||||
this.queryParams.lastWorkUpdateTimeStart = null;
|
this.queryParams.lastWorkUpdateTimeStart = null;
|
||||||
this.queryParams.lastWorkUpdateTimeEnd = 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() {
|
handleQuery() {
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
|
|
@ -739,8 +369,6 @@ export default {
|
||||||
this.queryParams.lastWorkUpdateTimeStart = null;
|
this.queryParams.lastWorkUpdateTimeStart = null;
|
||||||
this.queryParams.lastWorkUpdateTimeEnd = null;
|
this.queryParams.lastWorkUpdateTimeEnd = null;
|
||||||
this.queryParams.industryType = null; // Clear industry type
|
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();
|
this.handleQuery();
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
|
|
@ -751,74 +379,18 @@ export default {
|
||||||
},
|
},
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
handleAdd() {
|
handleAdd() {
|
||||||
this.reset();
|
this.selectedProjectId = null;
|
||||||
this.open = true;
|
this.projectFormVisible = true;
|
||||||
this.title = "添加项目管理";
|
|
||||||
},
|
},
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
handleUpdate(row) {
|
handleUpdate(row) {
|
||||||
this.reset();
|
this.selectedProjectId = row.id;
|
||||||
const id = row.id || this.ids
|
this.projectFormVisible = true;
|
||||||
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 = "修改项目管理";
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
/** 提交按钮 */
|
/** 表单提交成功 */
|
||||||
submitForm() {
|
handleFormSuccess() {
|
||||||
this.$refs["form"].validate(valid => {
|
this.projectFormVisible = false;
|
||||||
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();
|
this.getList();
|
||||||
});
|
|
||||||
} else {
|
|
||||||
addProject(this.form).then(response => {
|
|
||||||
this.$modal.msgSuccess("新增成功");
|
|
||||||
this.open = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
|
|
@ -850,75 +422,10 @@ export default {
|
||||||
}
|
}
|
||||||
return '';
|
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) {
|
handleView(row) {
|
||||||
// This would typically open a new route or a larger dialog for project details
|
this.currentProjectId = row.id;
|
||||||
this.$modal.alert("查看项目详情,ID: " + id);
|
this.drawerVisible = true;
|
||||||
},
|
},
|
||||||
/** 生成订单 */
|
/** 生成订单 */
|
||||||
openOrder(id, canGenerate) {
|
openOrder(id, canGenerate) {
|
||||||
|
|
@ -927,7 +434,6 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$modal.alert("生成订单,项目ID: " + id);
|
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>
|
<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 :model="queryParams" ref="queryForm" size="small" :inline="true">
|
||||||
<el-form-item label="产品编码" prop="productCode">
|
<el-form-item label="产品编码" prop="productCode">
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -38,6 +39,7 @@
|
||||||
:limit.sync="queryParams.pageSize"
|
:limit.sync="queryParams.pageSize"
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button @click="handleClose">取 消</el-button>
|
<el-button @click="handleClose">取 消</el-button>
|
||||||
|
|
@ -74,19 +76,19 @@ export default {
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
productCode: null,
|
productCode: null,
|
||||||
model: null,
|
model: null,
|
||||||
productType: this.productType // Pass productType to query params
|
type: this.productType // Pass productType to query params
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
visible(val) {
|
visible(val) {
|
||||||
if (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();
|
this.getList();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
productType(val) {
|
productType(val) {
|
||||||
this.queryParams.productType = val;
|
this.queryParams.type = val;
|
||||||
if (this.visible) {
|
if (this.visible) {
|
||||||
this.getList();
|
this.getList();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue