feat: 添加项目负责人联系信息字段及自动填充功能

- 在 Report、ReportDTO、ReportVO、ReportUpdateDTO 实体类中新增 contactPerson 和 contactPhone 字段
- 在 UserInfoVO 中新增 dealerContactPerson 和 dealerContactPhone 字段以展示经销商联系人信息
- 修改 ReportServiceImpl,在创建报备时自动填充默认的项目负责人信息(取自经销商信息)
- 更新 MyBatis 映射文件,确保数据库字段的正确映射和持久化
- 在前端 Report.vue 中添加相应的表单字段和表格列,并在新增时自动填充默认值
- 调整对话框宽度以适配新增字段
This commit is contained in:
wanglongjie 2026-02-03 17:01:46 +08:00
parent 8d82781bb3
commit e39c6816fc
11 changed files with 165 additions and 6 deletions

View File

@ -40,4 +40,14 @@ public class ReportDTO implements Serializable {
* 报备说明
*/
private String description;
/**
* 项目负责人姓名
*/
private String contactPerson;
/**
* 项目负责人电话
*/
private String contactPhone;
}

View File

@ -31,6 +31,16 @@ public class ReportUpdateDTO implements Serializable {
*/
private String description;
/**
* 项目负责人姓名
*/
private String contactPerson;
/**
* 项目负责人电话
*/
private String contactPhone;
/**
* 状态
*/

View File

@ -50,6 +50,16 @@ public class Report implements Serializable {
*/
private String description;
/**
* 项目负责人姓名
*/
private String contactPerson;
/**
* 项目负责人电话
*/
private String contactPhone;
/**
* 状态0-待审核 1-已通过 2-已驳回 3-已失效 4-已作废
*/

View File

@ -6,10 +6,12 @@ import com.bycrm.dto.PageQuery;
import com.bycrm.dto.ReportAuditDTO;
import com.bycrm.dto.ReportDTO;
import com.bycrm.dto.ReportUpdateDTO;
import com.bycrm.entity.Dealer;
import com.bycrm.entity.Report;
import com.bycrm.entity.School;
import com.bycrm.entity.User;
import com.bycrm.exception.BusinessException;
import com.bycrm.mapper.DealerMapper;
import com.bycrm.mapper.ReportMapper;
import com.bycrm.mapper.SchoolMapper;
import com.bycrm.mapper.UserMapper;
@ -35,15 +37,18 @@ public class ReportServiceImpl implements ReportService {
private final ReportMapper reportMapper;
private final SchoolMapper schoolMapper;
private final UserMapper userMapper;
private final DealerMapper dealerMapper;
private final SystemConfigService systemConfigService;
public ReportServiceImpl(ReportMapper reportMapper,
SchoolMapper schoolMapper,
UserMapper userMapper,
DealerMapper dealerMapper,
SystemConfigService systemConfigService) {
this.reportMapper = reportMapper;
this.schoolMapper = schoolMapper;
this.userMapper = userMapper;
this.dealerMapper = dealerMapper;
this.systemConfigService = systemConfigService;
}
@ -121,6 +126,27 @@ public class ReportServiceImpl implements ReportService {
}
}
// 查询经销商信息获取默认的联系人信息
String defaultContactPerson = null;
String defaultContactPhone = null;
if (currentUser.getDealerId() != null) {
Dealer dealer = dealerMapper.selectById(currentUser.getDealerId());
if (dealer != null) {
defaultContactPerson = dealer.getContactPerson();
defaultContactPhone = dealer.getContactPhone();
}
}
// 如果用户没有填写联系人信息使用经销商信息作为默认值
String contactPerson = reportDTO.getContactPerson();
if (contactPerson == null || contactPerson.trim().isEmpty()) {
contactPerson = defaultContactPerson;
}
String contactPhone = reportDTO.getContactPhone();
if (contactPhone == null || contactPhone.trim().isEmpty()) {
contactPhone = defaultContactPhone;
}
// 创建报备
Report report = new Report();
report.setDealerId(currentUser.getDealerId());
@ -129,6 +155,8 @@ public class ReportServiceImpl implements ReportService {
report.setProduct(reportDTO.getProduct());
report.setProjectType(reportDTO.getProjectType());
report.setDescription(reportDTO.getDescription());
report.setContactPerson(contactPerson);
report.setContactPhone(contactPhone);
report.setStatus(Constants.REPORT_STATUS_PENDING);
report.setCreatedAt(LocalDateTime.now());
report.setUpdatedAt(LocalDateTime.now());
@ -203,6 +231,8 @@ public class ReportServiceImpl implements ReportService {
report.setProduct(updateDTO.getProduct());
report.setProjectType(updateDTO.getProjectType());
report.setDescription(updateDTO.getDescription());
report.setContactPerson(updateDTO.getContactPerson());
report.setContactPhone(updateDTO.getContactPhone());
report.setStatus(updateDTO.getStatus());
report.setCancelReason(updateDTO.getCancelReason());
report.setUpdatedAt(LocalDateTime.now());

View File

@ -3,8 +3,10 @@ package com.bycrm.service.impl;
import com.bycrm.common.Constants;
import com.bycrm.dto.ChangePasswordDTO;
import com.bycrm.dto.ResetPasswordDTO;
import com.bycrm.entity.Dealer;
import com.bycrm.entity.User;
import com.bycrm.exception.BusinessException;
import com.bycrm.mapper.DealerMapper;
import com.bycrm.mapper.UserMapper;
import com.bycrm.service.UserService;
import com.bycrm.util.JwtUtil;
@ -20,11 +22,13 @@ public class UserServiceImpl implements UserService {
private final UserMapper userMapper;
private final JwtUtil jwtUtil;
private final DealerMapper dealerMapper;
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
public UserServiceImpl(UserMapper userMapper, JwtUtil jwtUtil) {
public UserServiceImpl(UserMapper userMapper, JwtUtil jwtUtil, DealerMapper dealerMapper) {
this.userMapper = userMapper;
this.jwtUtil = jwtUtil;
this.dealerMapper = dealerMapper;
}
@Override
@ -71,6 +75,16 @@ public class UserServiceImpl implements UserService {
vo.setDealerName(user.getDealerName());
vo.setRole(user.getRole());
vo.setRoleDesc(user.getRole() == Constants.USER_ROLE_ADMIN ? "管理员" : "经销商用户");
// 如果是经销商用户查询经销商的联系人信息
if (user.getDealerId() != null) {
Dealer dealer = dealerMapper.selectById(user.getDealerId());
if (dealer != null) {
vo.setDealerContactPerson(dealer.getContactPerson());
vo.setDealerContactPhone(dealer.getContactPhone());
}
}
return vo;
}

View File

@ -55,6 +55,16 @@ public class ReportVO implements Serializable {
*/
private String description;
/**
* 项目负责人姓名
*/
private String contactPerson;
/**
* 项目负责人电话
*/
private String contactPhone;
/**
* 状态0-待审核 1-已通过 2-已驳回 3-已失效 4-已作废
*/

View File

@ -37,6 +37,16 @@ public class UserInfoVO implements Serializable {
*/
private String dealerName;
/**
* 经销商联系人
*/
private String dealerContactPerson;
/**
* 经销商联系电话
*/
private String dealerContactPhone;
/**
* 角色0-管理员 1-经销商用户
*/

View File

@ -11,6 +11,8 @@
<result column="product" property="product"/>
<result column="project_type" property="projectType"/>
<result column="description" property="description"/>
<result column="contact_person" property="contactPerson"/>
<result column="contact_phone" property="contactPhone"/>
<result column="status" property="status"/>
<result column="reject_reason" property="rejectReason"/>
<result column="cancel_reason" property="cancelReason"/>
@ -91,8 +93,8 @@
</select>
<insert id="insert" parameterType="com.bycrm.entity.Report" useGeneratedKeys="true" keyProperty="id">
INSERT INTO crm_report (dealer_id, school_id, school_name, product, project_type, description, status, protect_start_date, protect_end_date)
VALUES (#{dealerId}, #{schoolId}, #{schoolName}, #{product}, #{projectType}, #{description}, #{status}, #{protectStartDate}, #{protectEndDate})
INSERT INTO crm_report (dealer_id, school_id, school_name, product, project_type, description, contact_person, contact_phone, status, protect_start_date, protect_end_date)
VALUES (#{dealerId}, #{schoolId}, #{schoolName}, #{product}, #{projectType}, #{description}, #{contactPerson}, #{contactPhone}, #{status}, #{protectStartDate}, #{protectEndDate})
</insert>
<update id="update" parameterType="com.bycrm.entity.Report">
@ -101,6 +103,8 @@
<if test="product != null">product = #{product},</if>
<if test="projectType != null">project_type = #{projectType},</if>
<if test="description != null">description = #{description},</if>
<if test="contactPerson != null">contact_person = #{contactPerson},</if>
<if test="contactPhone != null">contact_phone = #{contactPhone},</if>
<if test="status != null">status = #{status},</if>
<if test="rejectReason != null">reject_reason = #{rejectReason},</if>
<if test="cancelReason != null">cancel_reason = #{cancelReason},</if>

Binary file not shown.

View File

@ -5,6 +5,8 @@ export interface User {
realName: string
dealerId?: number
dealerName?: string
dealerContactPerson?: string
dealerContactPhone?: string
role: number
roleDesc: string
}
@ -65,6 +67,8 @@ export interface Report {
product?: string
projectType?: string
description?: string
contactPerson?: string
contactPhone?: string
status: number
statusDesc: string
rejectReason?: string
@ -82,6 +86,8 @@ export interface ReportForm {
product: string
projectType: string
description?: string
contactPerson?: string
contactPhone?: string
}
export interface ReportAuditForm {
@ -93,6 +99,8 @@ export interface ReportUpdateForm {
product: string
projectType: string
description?: string
contactPerson?: string
contactPhone?: string
status: number
cancelReason?: string
}

View File

@ -45,6 +45,8 @@
<el-table-column prop="schoolName" label="学校名称" />
<el-table-column prop="product" label="所属产品" show-overflow-tooltip />
<el-table-column prop="projectType" label="项目类型" show-overflow-tooltip />
<el-table-column prop="contactPerson" label="负责人" show-overflow-tooltip />
<el-table-column prop="contactPhone" label="负责人电话" show-overflow-tooltip />
<el-table-column prop="description" label="报备说明" show-overflow-tooltip />
<el-table-column prop="status" label="状态">
<template #default="{ row }">
@ -118,7 +120,7 @@
</el-card>
<!-- 提交报备对话框 -->
<el-dialog v-model="dialogVisible" title="提交报备" width="600px" @close="handleDialogClose">
<el-dialog v-model="dialogVisible" title="提交报备" width="650px" @close="handleDialogClose">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="学校" prop="schoolName">
<el-autocomplete
@ -151,6 +153,20 @@
clearable
/>
</el-form-item>
<el-form-item label="负责人" prop="contactPerson">
<el-input
v-model="formData.contactPerson"
placeholder="请输入负责人姓名"
clearable
/>
</el-form-item>
<el-form-item label="负责人电话" prop="contactPhone">
<el-input
v-model="formData.contactPhone"
placeholder="请输入负责人电话"
clearable
/>
</el-form-item>
<el-form-item label="报备说明" prop="description">
<el-input
v-model="formData.description"
@ -210,6 +226,20 @@
clearable
/>
</el-form-item>
<el-form-item label="负责人" prop="contactPerson">
<el-input
v-model="editFormData.contactPerson"
placeholder="请输入负责人姓名"
clearable
/>
</el-form-item>
<el-form-item label="负责人电话" prop="contactPhone">
<el-input
v-model="editFormData.contactPhone"
placeholder="请输入负责人电话"
clearable
/>
</el-form-item>
<el-form-item label="报备说明" prop="description">
<el-input
v-model="editFormData.description"
@ -254,6 +284,12 @@
<el-descriptions-item label="项目类型">
{{ currentReport?.projectType || '-' }}
</el-descriptions-item>
<el-descriptions-item label="项目负责人">
{{ currentReport?.contactPerson || '-' }}
</el-descriptions-item>
<el-descriptions-item label="项目电话">
{{ currentReport?.contactPhone || '-' }}
</el-descriptions-item>
<el-descriptions-item label="状态" :span="2">
<el-tag v-if="currentReport?.status === 0" type="warning">待审核</el-tag>
<el-tag v-else-if="currentReport?.status === 1" type="success">已通过</el-tag>
@ -398,7 +434,9 @@ const formData = reactive<ReportForm>({
schoolName: '',
product: '',
projectType: '',
description: ''
description: '',
contactPerson: '',
contactPhone: ''
})
const auditForm = reactive({
@ -410,6 +448,8 @@ const editFormData = reactive<ReportUpdateForm>({
product: '',
projectType: '',
description: '',
contactPerson: '',
contactPhone: '',
status: 1,
cancelReason: ''
})
@ -559,6 +599,13 @@ const handleReset = () => {
//
const handleAdd = () => {
//
if (userStore.userInfo?.dealerContactPerson) {
formData.contactPerson = userStore.userInfo.dealerContactPerson
}
if (userStore.userInfo?.dealerContactPhone) {
formData.contactPhone = userStore.userInfo.dealerContactPhone
}
dialogVisible.value = true
}
@ -583,6 +630,8 @@ const handleEdit = (row: Report) => {
editFormData.product = row.product || ''
editFormData.projectType = row.projectType || ''
editFormData.description = row.description || ''
editFormData.contactPerson = row.contactPerson || ''
editFormData.contactPhone = row.contactPhone || ''
editFormData.status = row.status
editFormData.cancelReason = row.cancelReason || ''
editDialogVisible.value = true
@ -595,6 +644,8 @@ const handleEditDialogClose = () => {
product: '',
projectType: '',
description: '',
contactPerson: '',
contactPhone: '',
status: 1,
cancelReason: ''
})
@ -683,7 +734,9 @@ const handleDialogClose = () => {
schoolName: '',
product: '',
projectType: '',
description: ''
description: '',
contactPerson: '',
contactPhone: ''
})
selectedSchool.value = null
}