客户关联产品开发
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
package com.gear.oa.controller;
|
||||
|
||||
import com.gear.common.annotation.Log;
|
||||
import com.gear.common.annotation.RepeatSubmit;
|
||||
import com.gear.common.core.controller.BaseController;
|
||||
import com.gear.common.core.domain.R;
|
||||
import com.gear.common.core.validate.AddGroup;
|
||||
import com.gear.common.enums.BusinessType;
|
||||
import com.gear.oa.domain.bo.GearCustomerProductBo;
|
||||
import com.gear.oa.domain.vo.GearCustomerProductVo;
|
||||
import com.gear.oa.service.IGearCustomerProductService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户-产品关联
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/oa/customerProduct")
|
||||
public class GearCustomerProductController extends BaseController {
|
||||
|
||||
private final IGearCustomerProductService iGearCustomerProductService;
|
||||
|
||||
/**
|
||||
* 查询客户关联产品列表
|
||||
*/
|
||||
@GetMapping("/customer/{customerId}")
|
||||
public R<List<GearCustomerProductVo>> listByCustomer(@NotNull(message = "客户ID不能为空")
|
||||
@PathVariable Long customerId) {
|
||||
return R.ok(iGearCustomerProductService.queryByCustomerId(customerId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询产品关联客户列表
|
||||
*/
|
||||
@GetMapping("/product/{productId}")
|
||||
public R<List<GearCustomerProductVo>> listByProduct(@NotNull(message = "产品ID不能为空")
|
||||
@PathVariable Long productId) {
|
||||
return R.ok(iGearCustomerProductService.queryByProductId(productId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增客户关联产品
|
||||
*/
|
||||
@Log(title = "客户关联产品", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody GearCustomerProductBo bo) {
|
||||
return toAjax(iGearCustomerProductService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除客户关联产品
|
||||
*/
|
||||
@Log(title = "客户关联产品", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{relationIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "关联ID不能为空")
|
||||
@PathVariable Long[] relationIds) {
|
||||
return toAjax(iGearCustomerProductService.deleteWithValidByIds(Arrays.asList(relationIds), true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.gear.oa.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.gear.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 客户-产品关联对象 gear_customer_product
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("gear_customer_product")
|
||||
public class GearCustomerProduct extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 关联ID
|
||||
*/
|
||||
@TableId(value = "relation_id")
|
||||
private Long relationId;
|
||||
|
||||
/**
|
||||
* 客户ID
|
||||
*/
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 产品ID
|
||||
*/
|
||||
private Long productId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 删除标志(0=正常,1=已删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer delFlag;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.gear.oa.domain.bo;
|
||||
|
||||
import com.gear.common.core.domain.BaseEntity;
|
||||
import com.gear.common.core.validate.AddGroup;
|
||||
import com.gear.common.core.validate.EditGroup;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 客户-产品关联业务对象
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class GearCustomerProductBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 关联ID
|
||||
*/
|
||||
@NotNull(message = "关联ID不能为空", groups = EditGroup.class)
|
||||
private Long relationId;
|
||||
|
||||
/**
|
||||
* 客户ID
|
||||
*/
|
||||
@NotNull(message = "客户ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 产品ID
|
||||
*/
|
||||
@NotNull(message = "产品ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long productId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.gear.oa.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 客户-产品关联视图对象
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class GearCustomerProductVo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ExcelProperty(value = "关联ID")
|
||||
private Long relationId;
|
||||
|
||||
@ExcelProperty(value = "客户ID")
|
||||
private Long customerId;
|
||||
|
||||
@ExcelProperty(value = "客户名称")
|
||||
private String customerName;
|
||||
|
||||
@ExcelProperty(value = "产品ID")
|
||||
private Long productId;
|
||||
|
||||
@ExcelProperty(value = "产品编号")
|
||||
private String productCode;
|
||||
|
||||
@ExcelProperty(value = "产品名称")
|
||||
private String productName;
|
||||
|
||||
@ExcelProperty(value = "负责人")
|
||||
private String owner;
|
||||
|
||||
@ExcelProperty(value = "单位")
|
||||
private String unit;
|
||||
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.gear.oa.mapper;
|
||||
|
||||
import com.gear.common.core.mapper.BaseMapperPlus;
|
||||
import com.gear.oa.domain.GearCustomerProduct;
|
||||
import com.gear.oa.domain.vo.GearCustomerProductVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户-产品关联Mapper接口
|
||||
*/
|
||||
public interface GearCustomerProductMapper extends BaseMapperPlus<GearCustomerProductMapper, GearCustomerProduct, GearCustomerProductVo> {
|
||||
|
||||
/**
|
||||
* 按客户查询关联产品
|
||||
*/
|
||||
List<GearCustomerProductVo> selectByCustomerId(@Param("customerId") Long customerId);
|
||||
|
||||
/**
|
||||
* 按产品查询关联客户
|
||||
*/
|
||||
List<GearCustomerProductVo> selectByProductId(@Param("productId") Long productId);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.gear.oa.service;
|
||||
|
||||
import com.gear.oa.domain.bo.GearCustomerProductBo;
|
||||
import com.gear.oa.domain.vo.GearCustomerProductVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户-产品关联Service接口
|
||||
*/
|
||||
public interface IGearCustomerProductService {
|
||||
|
||||
/**
|
||||
* 按客户查询关联产品
|
||||
*/
|
||||
List<GearCustomerProductVo> queryByCustomerId(Long customerId);
|
||||
|
||||
/**
|
||||
* 按产品查询关联客户
|
||||
*/
|
||||
List<GearCustomerProductVo> queryByProductId(Long productId);
|
||||
|
||||
/**
|
||||
* 新增客户-产品关联
|
||||
*/
|
||||
Boolean insertByBo(GearCustomerProductBo bo);
|
||||
|
||||
/**
|
||||
* 批量删除客户-产品关联
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.gear.oa.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.gear.common.exception.ServiceException;
|
||||
import com.gear.oa.domain.GearCustomerProduct;
|
||||
import com.gear.oa.domain.bo.GearCustomerProductBo;
|
||||
import com.gear.oa.domain.vo.GearCustomerProductVo;
|
||||
import com.gear.oa.mapper.GearCustomerMapper;
|
||||
import com.gear.oa.mapper.GearCustomerProductMapper;
|
||||
import com.gear.oa.mapper.GearProductMapper;
|
||||
import com.gear.oa.service.IGearCustomerProductService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户-产品关联Service业务层处理
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class GearCustomerProductServiceImpl implements IGearCustomerProductService {
|
||||
|
||||
private final GearCustomerProductMapper baseMapper;
|
||||
private final GearCustomerMapper customerMapper;
|
||||
private final GearProductMapper productMapper;
|
||||
|
||||
@Override
|
||||
public List<GearCustomerProductVo> queryByCustomerId(Long customerId) {
|
||||
return baseMapper.selectByCustomerId(customerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GearCustomerProductVo> queryByProductId(Long productId) {
|
||||
return baseMapper.selectByProductId(productId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean insertByBo(GearCustomerProductBo bo) {
|
||||
validEntityBeforeSave(bo);
|
||||
GearCustomerProduct add = BeanUtil.toBean(bo, GearCustomerProduct.class);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setRelationId(add.getRelationId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid && (ids == null || ids.isEmpty())) {
|
||||
throw new ServiceException("关联ID不能为空");
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
private void validEntityBeforeSave(GearCustomerProductBo bo) {
|
||||
if (bo.getCustomerId() == null) {
|
||||
throw new ServiceException("客户不能为空");
|
||||
}
|
||||
if (bo.getProductId() == null) {
|
||||
throw new ServiceException("产品不能为空");
|
||||
}
|
||||
if (customerMapper.selectById(bo.getCustomerId()) == null) {
|
||||
throw new ServiceException("客户不存在");
|
||||
}
|
||||
if (productMapper.selectById(bo.getProductId()) == null) {
|
||||
throw new ServiceException("产品不存在");
|
||||
}
|
||||
Long count = baseMapper.selectCount(
|
||||
Wrappers.<GearCustomerProduct>lambdaQuery()
|
||||
.eq(GearCustomerProduct::getCustomerId, bo.getCustomerId())
|
||||
.eq(GearCustomerProduct::getProductId, bo.getProductId())
|
||||
);
|
||||
if (count != null && count > 0) {
|
||||
throw new ServiceException("该客户已关联此产品,请勿重复添加");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.gear.oa.mapper.GearCustomerProductMapper">
|
||||
|
||||
<resultMap type="com.gear.oa.domain.GearCustomerProduct" id="GearCustomerProductResult">
|
||||
<result property="relationId" column="relation_id"/>
|
||||
<result property="customerId" column="customer_id"/>
|
||||
<result property="productId" column="product_id"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="delFlag" column="del_flag"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectByCustomerId" resultType="com.gear.oa.domain.vo.GearCustomerProductVo">
|
||||
select
|
||||
cp.relation_id,
|
||||
cp.customer_id,
|
||||
c.name as customer_name,
|
||||
cp.product_id,
|
||||
p.product_code,
|
||||
p.product_name,
|
||||
p.owner,
|
||||
p.unit,
|
||||
cp.remark,
|
||||
cp.create_time
|
||||
from gear_customer_product cp
|
||||
left join gear_customer c on c.customer_id = cp.customer_id and c.del_flag = 0
|
||||
left join gear_product p on p.product_id = cp.product_id and p.del_flag = 0
|
||||
where cp.del_flag = 0
|
||||
and cp.customer_id = #{customerId}
|
||||
order by cp.create_time desc, cp.relation_id desc
|
||||
</select>
|
||||
|
||||
<select id="selectByProductId" resultType="com.gear.oa.domain.vo.GearCustomerProductVo">
|
||||
select
|
||||
cp.relation_id,
|
||||
cp.customer_id,
|
||||
c.name as customer_name,
|
||||
cp.product_id,
|
||||
p.product_code,
|
||||
p.product_name,
|
||||
p.owner,
|
||||
p.unit,
|
||||
cp.remark,
|
||||
cp.create_time
|
||||
from gear_customer_product cp
|
||||
left join gear_customer c on c.customer_id = cp.customer_id and c.del_flag = 0
|
||||
left join gear_product p on p.product_id = cp.product_id and p.del_flag = 0
|
||||
where cp.del_flag = 0
|
||||
and cp.product_id = #{productId}
|
||||
order by cp.create_time desc, cp.relation_id desc
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -42,3 +42,28 @@ export function delProduct(productId) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询产品关联客户
|
||||
export function listProductCustomers(productId) {
|
||||
return request({
|
||||
url: '/oa/customerProduct/product/' + productId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增产品关联客户
|
||||
export function addProductCustomer(data) {
|
||||
return request({
|
||||
url: '/oa/customerProduct',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除产品关联客户
|
||||
export function delProductCustomer(relationId) {
|
||||
return request({
|
||||
url: '/oa/customerProduct/' + relationId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,3 +42,28 @@ export function delCustomer(customerId) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询客户关联产品
|
||||
export function listCustomerProducts(customerId) {
|
||||
return request({
|
||||
url: '/oa/customerProduct/customer/' + customerId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增客户关联产品
|
||||
export function addCustomerProduct(data) {
|
||||
return request({
|
||||
url: '/oa/customerProduct',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除客户关联产品
|
||||
export function delCustomerProduct(relationId) {
|
||||
return request({
|
||||
url: '/oa/customerProduct/' + relationId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
<el-tab-pane :label="entityType === 'customer' ? '客户详情' : '供货商详情'" name="detail" />
|
||||
<el-tab-pane label="信息编辑" name="edit" />
|
||||
<el-tab-pane v-if="entityType === 'customer'" label="历史订单" name="orders" />
|
||||
<el-tab-pane v-if="entityType === 'customer'" label="关联产品" name="products" />
|
||||
<el-tab-pane v-if="entityType === 'customer'" label="财务状态" name="finance" />
|
||||
<el-tab-pane v-if="entityType === 'customer'" label="订单异议" name="dispute" />
|
||||
<el-tab-pane v-if="entityType === 'customer'" label="发货单据" name="shipping" />
|
||||
@@ -214,6 +215,50 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="activeTab === 'products'">
|
||||
<div class="orders-section">
|
||||
<div class="finance-title-row">
|
||||
<div class="finance-title">关联产品</div>
|
||||
<div>
|
||||
<el-button size="small" plain type="primary" icon="Plus" :disabled="!selectedCustomerId" @click="openCustomerProductAdd">新增关联</el-button>
|
||||
<el-button size="small" plain icon="Refresh" :loading="productLoading" @click="loadCustomerProducts" style="margin-left: 8px;">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="productLoading" :data="customerProductList" border stripe :header-cell-style="{ background: '#f5f7fa' }">
|
||||
<el-table-column label="产品编号" prop="productCode" min-width="160" />
|
||||
<el-table-column label="产品名称" prop="productName" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column label="负责人" prop="owner" width="120" />
|
||||
<el-table-column label="单位" prop="unit" width="100" />
|
||||
<el-table-column label="备注" prop="remark" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column label="关联时间" prop="createTime" width="180" />
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="danger" @click="handleDeleteCustomerProduct(scope.row)">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog title="新增关联产品" v-model="customerProductAddOpen" width="520px" append-to-body>
|
||||
<el-form :model="customerProductForm" label-width="80px">
|
||||
<el-form-item label="客户">
|
||||
<el-input :model-value="selectedCustomer && selectedCustomer.name ? selectedCustomer.name : '-'" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品">
|
||||
<ProductSelect v-model="customerProductForm.productId" placeholder="请选择产品" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="customerProductForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="customerProductAddOpen = false">取消</el-button>
|
||||
<el-button type="primary" :loading="customerProductAddLoading" @click="submitCustomerProductAdd">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="activeTab === 'finance'">
|
||||
<div class="orders-section">
|
||||
<div class="finance-title-row">
|
||||
@@ -383,7 +428,7 @@
|
||||
|
||||
<script>
|
||||
import { getCurrentInstance } from "vue";
|
||||
import { listCustomer, getCustomer, delCustomer, addCustomer, updateCustomer } from "@/api/oms/customer";
|
||||
import { listCustomer, getCustomer, delCustomer, addCustomer, updateCustomer, listCustomerProducts, addCustomerProduct, delCustomerProduct } from "@/api/oms/customer";
|
||||
import { listSupplier, getSupplier, delSupplier, addSupplier, updateSupplier } from "@/api/oa/supplier";
|
||||
import { listSupplyType } from "@/api/oa/supplyType";
|
||||
import { listOrder } from "@/api/oms/order";
|
||||
@@ -392,11 +437,12 @@ import { listOrderDetail } from "@/api/oms/orderDetail";
|
||||
import { listReceivable } from "@/api/finance/receivable";
|
||||
import request from "@/utils/request";
|
||||
import DisputeFlow from "@/views/oms/order/panels/disputeFlow.vue";
|
||||
import ProductSelect from "@/components/ProductSelect/index.vue";
|
||||
import * as XLSX from "xlsx";
|
||||
|
||||
export default {
|
||||
name: "Customer",
|
||||
components: { DisputeFlow },
|
||||
components: { DisputeFlow, ProductSelect },
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { customer_from } = proxy.useDict("customer_from");
|
||||
@@ -456,6 +502,15 @@ export default {
|
||||
orderCode: undefined,
|
||||
salesManager: undefined
|
||||
},
|
||||
// 关联产品
|
||||
productLoading: false,
|
||||
customerProductList: [],
|
||||
customerProductAddOpen: false,
|
||||
customerProductAddLoading: false,
|
||||
customerProductForm: {
|
||||
productId: undefined,
|
||||
remark: ""
|
||||
},
|
||||
orderAmountMap: {},
|
||||
orderDeliveryMap: {},
|
||||
// 发货单据(右侧“发货单据”Tab 使用)
|
||||
@@ -564,6 +619,10 @@ export default {
|
||||
this.orderAmountMap = {};
|
||||
this.orderDeliveryMap = {};
|
||||
this.shippingList = [];
|
||||
this.customerProductList = [];
|
||||
this.customerProductAddOpen = false;
|
||||
this.customerProductAddLoading = false;
|
||||
this.customerProductForm = { productId: undefined, remark: "" };
|
||||
this.financeList = [];
|
||||
this.financeSummary = { receivableAmount: 0, receivedAmount: 0, unreceivedAmount: 0 };
|
||||
this.financeReceiveAddOpen = false;
|
||||
@@ -581,6 +640,9 @@ export default {
|
||||
if (this.activeTab === "orders") {
|
||||
this.loadOrders();
|
||||
}
|
||||
if (this.activeTab === "products") {
|
||||
this.loadCustomerProducts();
|
||||
}
|
||||
if (this.activeTab === "finance") {
|
||||
this.loadFinance();
|
||||
}
|
||||
@@ -719,6 +781,9 @@ export default {
|
||||
if (this.activeTab === "orders") {
|
||||
this.loadOrders();
|
||||
}
|
||||
if (this.activeTab === "products") {
|
||||
this.loadCustomerProducts();
|
||||
}
|
||||
if (this.activeTab === "finance") {
|
||||
this.loadFinance();
|
||||
}
|
||||
@@ -903,6 +968,58 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
openCustomerProductAdd() {
|
||||
if (!this.selectedCustomerId) return;
|
||||
this.customerProductForm = {
|
||||
productId: undefined,
|
||||
remark: ""
|
||||
};
|
||||
this.customerProductAddOpen = true;
|
||||
},
|
||||
|
||||
submitCustomerProductAdd() {
|
||||
if (!this.selectedCustomerId) return;
|
||||
if (!this.customerProductForm.productId) {
|
||||
this.$modal.msgError("请选择产品");
|
||||
return;
|
||||
}
|
||||
this.customerProductAddLoading = true;
|
||||
addCustomerProduct({
|
||||
customerId: this.selectedCustomerId,
|
||||
productId: this.customerProductForm.productId,
|
||||
remark: this.customerProductForm.remark || undefined
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess("关联成功");
|
||||
this.customerProductAddOpen = false;
|
||||
this.loadCustomerProducts();
|
||||
}).finally(() => {
|
||||
this.customerProductAddLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
loadCustomerProducts() {
|
||||
if (!this.selectedCustomerId) return;
|
||||
this.productLoading = true;
|
||||
listCustomerProducts(this.selectedCustomerId)
|
||||
.then(res => {
|
||||
this.customerProductList = (res && res.data) ? res.data : [];
|
||||
})
|
||||
.finally(() => {
|
||||
this.productLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
handleDeleteCustomerProduct(row) {
|
||||
const relationId = row && row.relationId ? row.relationId : undefined;
|
||||
if (!relationId) return;
|
||||
this.$modal.confirm("是否确认移除此关联产品?").then(() => {
|
||||
return delCustomerProduct(relationId);
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess("移除成功");
|
||||
this.loadCustomerProducts();
|
||||
}).catch(() => {});
|
||||
},
|
||||
|
||||
openDispute(row) {
|
||||
if (!row || !row.orderId) return;
|
||||
this.disputeOrderId = row.orderId;
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
<template #default="scope">
|
||||
<el-button size="small" type="text" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-button size="small" type="text" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
<el-button size="small" type="text" icon="User" @click="handleCustomerRelation(scope.row)">关联客户</el-button>
|
||||
<el-button size="small" type="text" icon="Document"
|
||||
@click="handleInstallManual(scope.row)">安装说明书</el-button>
|
||||
<el-button size="small" type="text" icon="DataAnalysis" @click="handleBom(scope.row)">BOM</el-button>
|
||||
@@ -128,13 +129,50 @@
|
||||
<el-button v-loading="buttonLoading" type="primary" @click="submitInstallManual">提交</el-button>
|
||||
<el-button @click="cancelInstallManual">取消</el-button>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="customerRelationTitle" v-model="customerRelationOpen" width="820px" append-to-body>
|
||||
<div class="customer-relation-toolbar">
|
||||
<div class="customer-relation-toolbar__title">已关联客户</div>
|
||||
<el-button type="primary" plain size="small" icon="Plus" @click="openCustomerRelationAdd">新增关联</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="customerRelationLoading" :data="customerRelationList" border stripe>
|
||||
<el-table-column label="客户名称" prop="customerName" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column label="备注" prop="remark" min-width="260" show-overflow-tooltip />
|
||||
<el-table-column label="关联时间" prop="createTime" width="180" />
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="danger" @click="handleDeleteProductCustomer(scope.row)">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog title="新增关联客户" v-model="customerRelationAddOpen" width="520px" append-to-body>
|
||||
<el-form :model="customerRelationForm" label-width="80px">
|
||||
<el-form-item label="产品">
|
||||
<el-input :model-value="selectedProduct && selectedProduct.productName ? selectedProduct.productName : '-'" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="客户">
|
||||
<CustomerSelect v-model="customerRelationForm.customerId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="customerRelationForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="customerRelationAddOpen = false">取消</el-button>
|
||||
<el-button type="primary" :loading="customerRelationAddLoading" @click="submitProductCustomerAdd">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listProduct, getProduct, delProduct, addProduct, updateProduct } from "@/api/oa/product";
|
||||
import { listProduct, getProduct, delProduct, addProduct, updateProduct, listProductCustomers, addProductCustomer, delProductCustomer } from "@/api/oa/product";
|
||||
import { listProductCategory } from "@/api/oa/productCategory";
|
||||
import UserSelect from '@/components/UserSelect';
|
||||
import CustomerSelect from '@/components/CustomerSelect';
|
||||
import BomPanel from '../components/BomPanel.vue';
|
||||
import BomInfoMini from '@/components/Renderer/BomInfoMini.vue';
|
||||
|
||||
@@ -142,6 +180,7 @@ export default {
|
||||
name: "Product",
|
||||
components: {
|
||||
UserSelect,
|
||||
CustomerSelect,
|
||||
BomPanel,
|
||||
BomInfoMini
|
||||
},
|
||||
@@ -205,6 +244,16 @@ export default {
|
||||
itemId: undefined,
|
||||
|
||||
installManualDialogVisible: false,
|
||||
customerRelationOpen: false,
|
||||
customerRelationLoading: false,
|
||||
customerRelationList: [],
|
||||
customerRelationAddOpen: false,
|
||||
customerRelationAddLoading: false,
|
||||
customerRelationForm: {
|
||||
customerId: '',
|
||||
remark: ''
|
||||
},
|
||||
selectedProduct: {},
|
||||
|
||||
showDetail: false,
|
||||
};
|
||||
@@ -293,6 +342,62 @@ export default {
|
||||
this.form = row;
|
||||
this.installManualDialogVisible = true;
|
||||
},
|
||||
handleCustomerRelation(row) {
|
||||
if (!row || !row.productId) return;
|
||||
this.selectedProduct = { ...row };
|
||||
this.customerRelationOpen = true;
|
||||
this.customerRelationAddOpen = false;
|
||||
this.customerRelationForm = {
|
||||
customerId: '',
|
||||
remark: ''
|
||||
};
|
||||
this.loadProductCustomers();
|
||||
},
|
||||
loadProductCustomers() {
|
||||
if (!this.selectedProduct || !this.selectedProduct.productId) return;
|
||||
this.customerRelationLoading = true;
|
||||
listProductCustomers(this.selectedProduct.productId).then(response => {
|
||||
this.customerRelationList = response && response.data ? response.data : [];
|
||||
}).finally(() => {
|
||||
this.customerRelationLoading = false;
|
||||
});
|
||||
},
|
||||
openCustomerRelationAdd() {
|
||||
this.customerRelationForm = {
|
||||
customerId: '',
|
||||
remark: ''
|
||||
};
|
||||
this.customerRelationAddOpen = true;
|
||||
},
|
||||
submitProductCustomerAdd() {
|
||||
if (!this.selectedProduct || !this.selectedProduct.productId) return;
|
||||
if (!this.customerRelationForm.customerId) {
|
||||
this.$modal.msgError("请选择客户");
|
||||
return;
|
||||
}
|
||||
this.customerRelationAddLoading = true;
|
||||
addProductCustomer({
|
||||
productId: this.selectedProduct.productId,
|
||||
customerId: this.customerRelationForm.customerId,
|
||||
remark: this.customerRelationForm.remark || undefined
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess("关联成功");
|
||||
this.customerRelationAddOpen = false;
|
||||
this.loadProductCustomers();
|
||||
}).finally(() => {
|
||||
this.customerRelationAddLoading = false;
|
||||
});
|
||||
},
|
||||
handleDeleteProductCustomer(row) {
|
||||
const relationId = row && row.relationId ? row.relationId : undefined;
|
||||
if (!relationId) return;
|
||||
this.$modal.confirm('是否确认移除此客户关联?').then(() => {
|
||||
return delProductCustomer(relationId);
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess("移除成功");
|
||||
this.loadProductCustomers();
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleBom(row) {
|
||||
this.bomDialogVisible = true;
|
||||
this.bomId = row.bomId;
|
||||
@@ -371,6 +476,28 @@ export default {
|
||||
...this.queryParams
|
||||
}, `product_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
customerRelationTitle() {
|
||||
const productName = this.selectedProduct && this.selectedProduct.productName ? this.selectedProduct.productName : "";
|
||||
return productName ? `关联客户 - ${productName}` : "关联客户";
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.customer-relation-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.customer-relation-toolbar__title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
CREATE TABLE IF NOT EXISTS `gear_customer_product` (
|
||||
`relation_id` bigint NOT NULL COMMENT '关联ID',
|
||||
`customer_id` bigint NOT NULL COMMENT '客户ID',
|
||||
`product_id` bigint NOT NULL COMMENT '产品ID',
|
||||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||||
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_by` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`del_flag` tinyint DEFAULT 0 COMMENT '删除标志(0=正常,1=已删除)',
|
||||
PRIMARY KEY (`relation_id`),
|
||||
KEY `idx_customer_product_customer` (`customer_id`),
|
||||
KEY `idx_customer_product_product` (`product_id`),
|
||||
KEY `idx_customer_product_del_flag` (`del_flag`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='客户-产品关联表';
|
||||
Reference in New Issue
Block a user