feat(project): 新增项目管理功能模块

- 实现项目信息的增删改查功能
- 添加项目筛选和搜索功能,支持多条件组合查询
- 集成项目导出功能
- 实现项目详情展示和编辑功能- 添加代表处、客户、进货商等关联信息选择器
- 支持项目阶段、行业、BG等字典数据展示- 实现项目金额格式化显示和输入校验
- 添加项目竞争对手信息管理功能
- 集成项目产品信息管理相关API接口
- 实现项目订单生成功能
- 添加权限控制和表单校验逻辑
dev_1.0.0
chenhao 2025-11-12 14:51:40 +08:00
parent e08751bdb2
commit 51d24b5dec
7 changed files with 1478 additions and 0 deletions

View File

@ -0,0 +1,53 @@
import request from '@/utils/request'
// 查询项目管理列表
export function listProject(query) {
return request({
url: '/sip/project/vue/list',
method: 'get',
params: query
})
}
// 查询项目管理详细
export function getProject(id) {
return request({
url: '/sip/project/vue/' + id,
method: 'get'
})
}
// 新增项目管理
export function addProject(data) {
return request({
url: '/sip/project/vue',
method: 'post',
data: data
})
}
// 修改项目管理
export function updateProject(data) {
return request({
url: '/sip/project/vue',
method: 'put',
data: data
})
}
// 删除项目管理
export function delProject(id) {
return request({
url: '/sip/project/vue/' + id,
method: 'delete'
})
}
// 导出项目管理
export function exportProject(query) {
return request({
url: '/sip/project/vue/export',
method: 'post',
params: query
})
}

View File

@ -0,0 +1,53 @@
import request from '@/utils/request'
// 查询产品信息列表
export function listProduct(query) {
return request({
url: '/system/product/vue/list',
method: 'get',
params: query
})
}
// 查询产品信息详细
export function getProduct(id) {
return request({
url: '/system/product/vue/' + id,
method: 'get'
})
}
// 新增产品信息
export function addProduct(data) {
return request({
url: '/system/product/vue',
method: 'post',
data: data
})
}
// 修改产品信息
export function updateProduct(data) {
return request({
url: '/system/product/vue',
method: 'put',
data: data
})
}
// 删除产品信息
export function delProduct(id) {
return request({
url: '/system/product/vue/' + id,
method: 'delete'
})
}
// 导出产品信息
export function exportProduct(query) {
return request({
url: '/system/product/vue/export',
method: 'post',
params: query
})
}

View File

@ -0,0 +1,934 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="项目编号" prop="projectCode">
<el-input
v-model="queryParams.projectCode"
placeholder="请输入项目编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
placeholder="请输入项目名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="最终客户" prop="customerName">
<el-input
v-model="queryParams.customerName"
placeholder="请输入最终客户"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="BG" prop="bgProperty">
<el-select v-model="queryParams.bgProperty" placeholder="请选择BG" clearable @change="handleSearchBgChange">
<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-form-item label="行业" prop="industryType">
<el-select v-model="queryParams.industryType" placeholder="请选择行业" clearable>
<el-option
v-for="item in searchIndustryOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="代表处" prop="agentName">
<el-input
v-model="queryParams.agentName"
placeholder="请输入代表处"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="项目把握度" prop="projectGraspDegree">
<el-select v-model="queryParams.projectGraspDegree" placeholder="请选择项目把握度" clearable>
<el-option label="A" value="A" />
<el-option label="B" value="B" />
<el-option label="C" value="C" />
</el-select>
</el-form-item>
<el-form-item label="项目阶段" prop="projectStage">
<el-select v-model="queryParams.projectStage" placeholder="请选择项目阶段" clearable multiple>
<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-form-item label="汇智负责人" prop="hzSupportUserName">
<el-input
v-model="queryParams.hzSupportUserName"
placeholder="请输入汇智负责人"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="POC" prop="poc">
<el-select v-model="queryParams.poc" placeholder="请选择POC" clearable>
<el-option label="是" value="1" />
<el-option label="否" value="0" />
</el-select>
</el-form-item>
<el-form-item label="时间选择" prop="timeType">
<el-select v-model="queryParams.timeType" placeholder="请选择时间类型" @change="handleTimeTypeChange">
<el-option label="预计下单时间" value="0" />
<el-option label="更新时间" value="2" />
</el-select>
</el-form-item>
<el-form-item label="" prop="dateRange">
<el-date-picker
v-model="dateRange"
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="['sip:project: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="['sip:project: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="['sip:project:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="projectList" @selection-change="handleSelectionChange">
<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">
<template slot-scope="scope">
<a @click="viewDetail(scope.row.id)" class="link-type">{{ scope.row.projectName }}</a>
</template>
</el-table-column>
<el-table-column label="最终客户" align="center" prop="customerName" width="200" />
<el-table-column label="BG" align="center" prop="bgProperty" width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.bg_type" :value="scope.row.bgProperty"/>
</template>
</el-table-column>
<el-table-column label="行业" align="center" prop="industryType" width="100">
<template slot-scope="scope">
<dict-tag v-if="scope.row.bgProperty === 'YYS'" :options="dict.type.bg_yys" :value="scope.row.industryType"/>
<dict-tag v-else :options="dict.type.bg_hysy" :value="scope.row.industryType"/>
</template>
</el-table-column>
<el-table-column label="代表处" align="center" prop="agentName" width="100" />
<el-table-column label="项目把握度" align="center" prop="projectGraspDegree" width="100" />
<el-table-column label="项目阶段" align="center" prop="projectStage" width="160">
<template slot-scope="scope">
<dict-tag :options="dict.type.project_stage" :value="scope.row.projectStage"/>
</template>
</el-table-column>
<el-table-column label="汇智负责人" align="center" prop="hzSupportUserName" width="100" />
<el-table-column label="POC" align="center" prop="poc" width="100">
<template slot-scope="scope">
<span>{{ scope.row.poc === '1' ? '是' : '否' }}</span>
</template>
</el-table-column>
<el-table-column label="预计金额(元)" align="center" prop="estimatedAmount" width="140" sortable="custom" :sort-orders="['descending', 'ascending']">
<template slot-scope="scope">
<span>{{ formatAmountNumber(scope.row.estimatedAmount) }}</span>
</template>
</el-table-column>
<el-table-column label="预计下单时间" align="center" prop="estimatedOrderTime" width="140" sortable="custom" :sort-orders="['descending', 'ascending']">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.estimatedOrderTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新时间" align="center" prop="lastWorkUpdateTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.lastWorkUpdateTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="300" fixed="right">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['sip:project:edit']"
>项目详情</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-refresh"
@click="openOrder(scope.row.id, scope.row.canGenerate)"
:disabled="!scope.row.canGenerate"
v-hasPermi="['sip:project:add']"
>生成订单</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['sip:project:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改项目管理对话框 -->
<el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body :close-on-click-modal="false">
<el-form ref="form" :model="form" :rules="rules" label-width="120px" style="max-height: 60vh; overflow-y: auto; padding-right: 20px;">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="form.projectCode" placeholder="保存后自动生成" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="form.projectName" placeholder="请输入项目名称" maxlength="40" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="BG" prop="bgProperty">
<el-select v-model="form.bgProperty" placeholder="请选择BG" @change="handleBgChange" style="width: 100%;">
<el-option
v-for="dict in dict.type.bg_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="行业" prop="industryType">
<el-select v-model="form.industryType" placeholder="请选择行业" style="width: 100%;">
<el-option
v-for="item in industryOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="代表处" prop="agentName">
<el-input v-model="form.agentName" placeholder="请选择代表处" readonly @click.native="openSelectAgent" />
<input type="hidden" v-model="form.agentCode" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="项目阶段" prop="projectStage">
<el-select v-model="form.projectStage" placeholder="请选择项目阶段" style="width: 100%;">
<el-option
v-for="dict in dict.type.project_stage"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="项目把握度" prop="projectGraspDegree">
<el-select v-model="form.projectGraspDegree" placeholder="请选择项目把握度" style="width: 100%;">
<el-option label="A" value="A" />
<el-option label="B" value="B" />
<el-option label="C" value="C" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="汇智负责人" prop="hzSupportUserName">
<el-input v-model="form.hzSupportUserName" placeholder="请选择汇智负责人" readonly @click.native="openSelectPeople" />
<input type="hidden" v-model="form.hzSupportUser" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="最终客户" prop="customerName">
<el-input v-model="form.customerName" placeholder="请选择最终客户" readonly @click.native="openSelectCustomer" />
<input type="hidden" v-model="form.customerCode" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="客户联系人" prop="customerUserName">
<el-input v-model="form.customerUserName" placeholder="请输入客户联系人" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="最终客户 TEL" prop="customerPhone">
<el-input v-model="form.customerPhone" placeholder="请输入最终客户电话" maxlength="11" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="运作方" prop="operateInstitution">
<el-select v-model="form.operateInstitution" placeholder="请选择运作方" @change="handleOperateInstitutionChange" style="width: 100%;">
<el-option
v-for="dict in dict.type.operate_institution"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="新华三联系人" prop="h3cPerson">
<el-input v-model="form.h3cPerson" placeholder="请输入新华三联系人" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="新华三TEL" prop="h3cPhone">
<el-input v-model="form.h3cPhone" placeholder="请输入新华三电话" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="进货商" prop="partnerName">
<el-input v-model="form.partnerName" placeholder="请选择进货商" readonly @click.native="openSelectPartner" />
<input type="hidden" v-model="form.partnerCode" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="进货商联系人" prop="partnerUserName">
<el-input v-model="form.partnerUserName" placeholder="请输入进货商联系人" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="进货商 TEL" prop="contactWay">
<el-input v-model="form.contactWay" placeholder="请输入进货商电话" maxlength="11" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="预计金额(元)" prop="estimatedAmount">
<el-input v-model="form.estimatedAmount" placeholder="请输入预计金额" @blur="formatEstimatedAmount" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="预计下单时间" prop="estimatedOrderTime">
<el-date-picker clearable
v-model="form.estimatedOrderTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择预计下单时间"
style="width: 100%;">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="POC测试" prop="poc">
<el-select v-model="form.poc" placeholder="请选择POC" style="width: 100%;">
<el-option label="是" value="1" />
<el-option label="否" value="0" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="是否国产" prop="countryProduct">
<el-select v-model="form.countryProduct" placeholder="请选择" style="width: 100%;">
<el-option label="是" value="1" />
<el-option label="否" value="0" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="竞争对手" >
<div>
<el-checkbox-group v-model="form.competitorList">
<el-checkbox label="华为" value="华为"></el-checkbox>
<el-checkbox label="锐捷" value="锐捷"></el-checkbox>
<el-checkbox label="深信服" value="深信服"></el-checkbox>
<el-checkbox label="中兴" value="中兴"></el-checkbox>
<el-checkbox label="噢易云" value="噢易云"></el-checkbox>
</el-checkbox-group>
</div>
<div style="margin-top: 10px;">
<el-input
v-model="form.otherCompetitor"
placeholder="其他竞争对手"
style="width: 400px;"
@click.native.stop
@mousedown.native.stop
/>
</div>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="关键技术问题" prop="keyProblem">
<el-input v-model="form.keyProblem" type="textarea" placeholder="请输入关键技术问题" maxlength="500" />
</el-form-item>
<el-form-item label="项目简述" prop="projectDesc">
<el-input v-model="form.projectDesc" type="textarea" placeholder="请输入项目简述" maxlength="500" />
</el-form-item>
<el-form-item label="服务器配置" prop="serverConfiguration">
<el-input v-model="form.serverConfiguration" type="textarea" placeholder="请输入服务器配置" maxlength="500" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<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 { listProject, getProject, delProject, addProject, updateProject, exportProject } from "@/api/project/info";
import { listAreas } from "@/api/system/area";
import SelectAgent from "../../system/agent/selectAgent.vue";
import SelectCustomer from "../../system/customer/selectCustomer.vue";
import SelectPartner from "../../system/partner/selectPartner.vue";
import SelectUser from "@/views/system/user/selectUser"; // Reusing the existing SelectUser component
export default {
name: "Project",
components: {
SelectAgent,
SelectCustomer,
SelectPartner,
SelectUser
},
dicts: ['bg_type', 'bg_yys', 'bg_hysy', 'project_stage', 'operate_institution'],
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
projectList: [],
//
title: "",
//
open: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
projectCode: null,
projectName: null,
customerName: null,
bgProperty: null,
industryType: null,
agentName: null,
projectGraspDegree: null,
projectStage: [],
hzSupportUserName: null,
poc: null,
timeType: '0', // Default to
estimatedOrderTimeStart: null,
estimatedOrderTimeEnd: null,
lastWorkUpdateTimeStart: null,
lastWorkUpdateTimeEnd: null,
},
dateRange: [],
//
provinceOptions: [],
//
cityOptions: [],
//
searchProvinceOptions: [],
//
searchCityOptions: [],
//
industryOptions: [],
//
searchIndustryOptions: [],
//
selectAgentVisible: false,
selectCustomerVisible: false,
selectPartnerVisible: false,
selectUserVisible: false,
selectProductVisible: false, //
currentProductRowIndex: null, //
currentProductListType: null, // (software, hardware, maintenance)
//
form: {
competitorList: [], // Initialize as array for checkboxes
otherCompetitor: null, // For the "" competitor input
softwareProjectProductInfoList: [],
hardwareProjectProductInfoList: [],
maintenanceProjectProductInfoList: [],
},
//
rules: {
projectName: [
{ required: true, message: "项目名称不能为空", trigger: "blur" }
],
bgProperty: [
{ required: true, message: "BG不能为空", trigger: "change" }
],
industryType: [
{ required: true, message: "行业不能为空", trigger: "change" }
],
agentName: [
{ required: true, message: "代表处不能为空", trigger: "change" }
],
projectStage: [
{ required: true, message: "项目阶段不能为空", trigger: "change" }
],
projectGraspDegree: [
{ required: true, message: "项目把握度不能为空", trigger: "change" }
],
customerName: [
{ required: true, message: "最终客户不能为空", trigger: "change" }
],
operateInstitution: [
{ required: true, message: "运作方不能为空", trigger: "change" }
],
estimatedAmount: [
{ required: true, message: "预计金额不能为空", trigger: "blur" }
],
projectDesc: [
{ required: true, message: "项目简述不能为空", trigger: "blur" }
],
h3cPerson: [
{ validator: (rule, value, callback) => {
if (this.form.operateInstitution === 'h3c' && !value) {
callback(new Error("新华三联系人不能为空"));
} else {
callback();
}
}, trigger: "blur" }
],
h3cPhone: [
{ validator: (rule, value, callback) => {
if (this.form.operateInstitution === 'h3c' && !value) {
callback(new Error("新华三TEL不能为空"));
} else {
callback();
}
}, trigger: "blur" }
],
}
};
},
created() {
this.getList();
this.getProvinceList(); // For selectAgent/selectCustomer/selectPartner
this.handleSearchBgChange(this.queryParams.bgProperty); // Initialize search industry options
},
watch: {
dateRange(val) {
if (val && val.length === 2) {
if (this.queryParams.timeType === '0') {
this.queryParams.estimatedOrderTimeStart = val[0];
this.queryParams.estimatedOrderTimeEnd = val[1];
this.queryParams.lastWorkUpdateTimeStart = null;
this.queryParams.lastWorkUpdateTimeEnd = null;
} else if (this.queryParams.timeType === '2') {
this.queryParams.lastWorkUpdateTimeStart = val[0];
this.queryParams.lastWorkUpdateTimeEnd = val[1];
this.queryParams.estimatedOrderTimeStart = null;
this.queryParams.estimatedOrderTimeEnd = null;
}
} else {
this.queryParams.estimatedOrderTimeStart = null;
this.queryParams.estimatedOrderTimeEnd = null;
this.queryParams.lastWorkUpdateTimeStart = null;
this.queryParams.lastWorkUpdateTimeEnd = null;
}
},
},
methods: {
/** 查询项目管理列表 */
getList() {
this.loading = true;
listProject(this.queryParams).then(response => {
this.projectList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 查询省份列表 (for selectAgent/selectCustomer/selectPartner) */
getProvinceList() {
listAreas(0).then(response => {
this.provinceOptions = response;
this.searchProvinceOptions = response;
});
},
/** 搜索省份选择改变时 */
handleSearchProvinceChange(provinceName) {
this.queryParams.city = null;
const selectedProvince = this.searchProvinceOptions.find(p => p.n === provinceName);
if (selectedProvince) {
this.searchCityOptions = selectedProvince.s;
} else {
this.searchCityOptions = [];
}
},
/** 省份选择改变时 (for add/edit dialog) */
handleProvinceChange(provinceName) {
this.form.city = null;
const selectedProvince = this.provinceOptions.find(p => p.n === provinceName);
if (selectedProvince) {
this.cityOptions = selectedProvince.s;
} else {
this.cityOptions = [];
}
},
/** 搜索BG选择改变时 */
handleSearchBgChange(bgValue) {
this.queryParams.industryType = null;
if (bgValue === 'YYS') {
this.searchIndustryOptions = this.dict.type.bg_yys;
} else if (bgValue) { // Only update if a BG is selected
this.searchIndustryOptions = this.dict.type.bg_hysy;
} else {
this.searchIndustryOptions = []; // Clear if no BG selected
}
},
/** BG选择改变时 (for add/edit dialog) */
handleBgChange(bgValue) {
this.form.industryType = null;
if (bgValue === 'YYS') {
this.industryOptions = this.dict.type.bg_yys;
} else if (bgValue) { // Only update if a BG is selected
this.industryOptions = this.dict.type.bg_hysy;
} else {
this.industryOptions = []; // Clear if no BG selected
}
},
/** 时间类型选择改变时 */
handleTimeTypeChange() {
this.dateRange = []; // Clear date range when time type changes
this.queryParams.estimatedOrderTimeStart = null;
this.queryParams.estimatedOrderTimeEnd = null;
this.queryParams.lastWorkUpdateTimeStart = null;
this.queryParams.lastWorkUpdateTimeEnd = null;
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: null,
projectCode: null,
projectName: null,
bgProperty: null,
industryType: null,
agentName: null,
agentCode: null,
projectStage: null,
projectGraspDegree: null,
hzSupportUserName: null,
hzSupportUser: null,
customerName: null,
customerCode: null,
customerUserName: null,
customerPhone: null,
operateInstitution: null,
h3cPerson: null,
h3cPhone: null,
partnerName: null,
partnerCode: null,
partnerUserName: null,
contactWay: null,
estimatedAmount: null,
estimatedOrderTime: null,
poc: '0', // Default to ''
competitorList: [],
otherCompetitor: '', //
countryProduct: null,
keyProblem: null,
projectDesc: null,
serverConfiguration: null,
createAt: null,
updatedAt: null
};
this.cityOptions = [];
this.industryOptions = [];
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.queryParams.timeType = '0'; // Reset timeType to default
this.queryParams.estimatedOrderTimeStart = null;
this.queryParams.estimatedOrderTimeEnd = null;
this.queryParams.lastWorkUpdateTimeStart = null;
this.queryParams.lastWorkUpdateTimeEnd = null;
this.queryParams.industryType = null; // Clear industry type
this.searchIndustryOptions = []; // Clear search industry options
this.handleSearchBgChange(this.queryParams.bgProperty); // Re-initialize search industry options based on default BG
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加项目管理";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids
getProject(id).then(response => {
this.form = response.data;
// otherCompetitor competitorList
this.$set(this.form, 'otherCompetitor', '');
this.$set(this.form, 'competitorList', []);
// Handle competitorList and otherCompetitor
if (this.form.competitor) {
const allCompetitors = this.form.competitor.split(",");
const predefinedCompetitors = ['华为', '锐捷', '深信服', '中兴', '噢易云'];
this.$set(this.form, 'otherCompetitor', allCompetitors.filter(c => !predefinedCompetitors.includes(c)).join(','));
this.$set(this.form, 'competitorList', allCompetitors.filter(c => predefinedCompetitors.includes(c)));
}
// Populate city options if province is already set
if (this.form.province) {
const selectedProvince = this.provinceOptions.find(p => p.n === this.form.province);
if (selectedProvince) {
this.cityOptions = selectedProvince.s;
}
}
// Populate industry options if bgProperty is already set
if (this.form.bgProperty) {
if (this.form.bgProperty === 'YYS') {
this.industryOptions = this.dict.type.bg_yys;
} else {
this.industryOptions = this.dict.type.bg_hysy;
}
}
this.open = true;
this.title = "修改项目管理";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
// Combine competitorList and otherCompetitor before submitting
let finalCompetitorList = [...this.form.competitorList];
if (this.form.otherCompetitor) {
finalCompetitorList = finalCompetitorList.concat(this.form.otherCompetitor.split(',').map(s => s.trim()).filter(s => s.length > 0));
}
this.form.competitorList = finalCompetitorList;
if (this.form.id != null) {
updateProject(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addProject(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除项目管理编号为"' + ids + '"的数据项?').then(function() {
return delProject(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.$modal.confirm('是否确认导出所有项目管理数据项?').then(() => {
this.loading = true;
return exportProject(this.queryParams);
}).then(response => {
this.loading = false;
const fileName = response.msg;
window.location.href = process.env.VUE_APP_BASE_API + "/common/download?fileName=" + encodeURIComponent(fileName) + "&delete=" + true;
}).catch(() => {
this.loading = false;
});
},
/** 格式化金额 */
formatAmountNumber(value) {
if (value) {
return Number(value).toLocaleString('en-US');
}
return '';
},
/** 金额输入框失去焦点时格式化 */
formatEstimatedAmount() {
if (this.form.estimatedAmount) {
this.form.estimatedAmount = this.form.estimatedAmount.replace(/[^0-9.]/g,'').replace(/(\..*)\./g, '$1');
}
},
/** 运作方选择改变时 */
handleOperateInstitutionChange(value) {
// ""
if (value === 'h3c') {
this.form.partnerName = '新华三';
this.form.partnerCode = null;
}
// TEL
if (this.$refs.form) {
this.$nextTick(() => {
this.$refs.form.validateField('h3cPerson');
this.$refs.form.validateField('h3cPhone');
});
}
},
/** 打开选择代表处对话框 */
openSelectAgent() {
this.selectAgentVisible = true;
},
/** 处理代表处选择 */
handleAgentSelected(agent) {
this.form.agentName = agent.agentName;
this.form.agentCode = agent.agentCode;
this.selectAgentVisible = false;
},
/** 打开选择客户对话框 */
openSelectCustomer() {
this.selectCustomerVisible = true;
},
/** 处理客户选择 */
handleCustomerSelected(customer) {
this.form.customerName = customer.customerName;
this.form.customerCode = customer.customerCode;
this.form.customerUserName = customer.contactPerson;
this.form.customerPhone = customer.contactPhone;
this.selectCustomerVisible = false;
},
/** 打开选择进货商对话框 */
openSelectPartner() {
this.selectPartnerVisible = true;
},
/** 处理进货商选择 */
handlePartnerSelected(partner) {
this.form.partnerName = partner.partnerName;
this.form.partnerCode = partner.partnerCode;
this.form.partnerUserName = partner.contactPerson;
this.form.contactWay = partner.contactPhone;
this.selectPartnerVisible = false;
},
/** 打开选择汇智负责人对话框 */
openSelectPeople() {
this.selectUserVisible = true;
},
/** 处理汇智负责人选择 */
handleUserSelected(user) {
this.form.hzSupportUserName = user.userName;
this.form.hzSupportUser = user.userId;
this.selectUserVisible = false;
},
/** 查看项目详情 */
viewDetail(id) {
// This would typically open a new route or a larger dialog for project details
this.$modal.alert("查看项目详情ID: " + id);
},
/** 生成订单 */
openOrder(id, canGenerate) {
if (!canGenerate) {
this.$modal.alertWarning("该项目已存在订单");
return;
}
this.$modal.alert("生成订单项目ID: " + id);
// This would typically open a new route or a larger dialog for order creation
},
}
};
</script>

View File

@ -0,0 +1,104 @@
<template>
<el-dialog title="选择代表处" :visible.sync="visible" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="代表处名称" prop="agentName">
<el-input
v-model="queryParams.agentName"
placeholder="请输入代表处名称"
clearable
@keyup.enter.native="handleQuery"
/>
</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-table v-loading="loading" :data="agentList" @row-click="handleRowClick">
<el-table-column label="代表处编码" align="center" prop="agentCode" />
<el-table-column label="代表处名称" align="center" prop="agentName" />
<el-table-column label="所在省" align="center" prop="province" />
<el-table-column label="所在市" align="center" prop="city" />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { listAgent } from "@/api/system/agent";
export default {
name: "SelectAgent",
props: {
visible: {
type: Boolean,
default: false,
},
},
data() {
return {
//
loading: true,
//
total: 0,
//
agentList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
agentName: null,
},
};
},
watch: {
visible(val) {
if (val) {
this.getList();
}
},
},
methods: {
/** 查询代表处列表 */
getList() {
this.loading = true;
listAgent(this.queryParams).then(response => {
this.agentList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 行点击事件 */
handleRowClick(row) {
this.$emit("agent-selected", row);
this.handleClose();
},
/** 关闭按钮 */
handleClose() {
this.$emit("update:visible", false);
},
},
};
</script>

View File

@ -0,0 +1,104 @@
<template>
<el-dialog title="选择客户" :visible.sync="visible" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="客户名称" prop="customerName">
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户名称"
clearable
@keyup.enter.native="handleQuery"
/>
</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-table v-loading="loading" :data="customerList" @row-click="handleRowClick">
<el-table-column label="客户编码" align="center" prop="customerCode" />
<el-table-column label="最终客户名称" align="center" prop="customerName" />
<el-table-column label="所在省" align="center" prop="province" />
<el-table-column label="所在市" align="center" prop="city" />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { listCustomer } from "@/api/system/customer";
export default {
name: "SelectCustomer",
props: {
visible: {
type: Boolean,
default: false,
},
},
data() {
return {
//
loading: true,
//
total: 0,
//
customerList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
customerName: null,
},
};
},
watch: {
visible(val) {
if (val) {
this.getList();
}
},
},
methods: {
/** 查询客户列表 */
getList() {
this.loading = true;
listCustomer(this.queryParams).then(response => {
this.customerList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 行点击事件 */
handleRowClick(row) {
this.$emit("customer-selected", row);
this.handleClose();
},
/** 关闭按钮 */
handleClose() {
this.$emit("update:visible", false);
},
},
};
</script>

View File

@ -0,0 +1,104 @@
<template>
<el-dialog title="选择进货商" :visible.sync="visible" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="进货商名称" prop="partnerName">
<el-input
v-model="queryParams.partnerName"
placeholder="请输入进货商名称"
clearable
@keyup.enter.native="handleQuery"
/>
</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-table v-loading="loading" :data="partnerList" @row-click="handleRowClick">
<el-table-column label="进货商编码" align="center" prop="partnerCode" />
<el-table-column label="进货商名称" align="center" prop="partnerName" />
<el-table-column label="所在省" align="center" prop="province" />
<el-table-column label="所在市" align="center" prop="city" />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { listPartner } from "@/api/system/partner";
export default {
name: "SelectPartner",
props: {
visible: {
type: Boolean,
default: false,
},
},
data() {
return {
//
loading: true,
//
total: 0,
//
partnerList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
partnerName: null,
},
};
},
watch: {
visible(val) {
if (val) {
this.getList();
}
},
},
methods: {
/** 查询进货商列表 */
getList() {
this.loading = true;
listPartner(this.queryParams).then(response => {
this.partnerList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 行点击事件 */
handleRowClick(row) {
this.$emit("partner-selected", row);
this.handleClose();
},
/** 关闭按钮 */
handleClose() {
this.$emit("update:visible", false);
},
},
};
</script>

View File

@ -0,0 +1,126 @@
<template>
<el-dialog title="选择产品" :visible.sync="visible" width="1000px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="产品编码" prop="productCode">
<el-input
v-model="queryParams.productCode"
placeholder="请输入产品编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="产品型号" prop="model">
<el-input
v-model="queryParams.model"
placeholder="请输入产品型号"
clearable
@keyup.enter.native="handleQuery"
/>
</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-table v-loading="loading" :data="productList" @row-click="handleRowClick">
<el-table-column label="产品编码" align="center" prop="productCode" />
<el-table-column label="产品型号" align="center" prop="model" />
<el-table-column label="产品描述" align="center" prop="description" />
<el-table-column label="目录单价(¥)" align="center" prop="cataloguePrice" />
<el-table-column label="指导折扣" align="center" prop="guidanceDiscount" />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { listProduct } from "@/api/project/product";
export default {
name: "SelectProduct",
props: {
visible: {
type: Boolean,
default: false,
},
productType: {
type: String,
default: '',
}
},
data() {
return {
//
loading: true,
//
total: 0,
//
productList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
productCode: null,
model: null,
productType: this.productType // Pass productType to query params
},
};
},
watch: {
visible(val) {
if (val) {
this.queryParams.productType = this.productType; // Update productType when dialog opens
this.getList();
}
},
productType(val) {
this.queryParams.productType = val;
if (this.visible) {
this.getList();
}
}
},
methods: {
/** 查询产品列表 */
getList() {
this.loading = true;
listProduct(this.queryParams).then(response => {
this.productList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 行点击事件 */
handleRowClick(row) {
this.$emit("product-selected", row);
this.handleClose();
},
/** 关闭按钮 */
handleClose() {
this.$emit("update:visible", false);
},
},
};
</script>