You need to sign in or sign up before continuing.
Commit 29054b48 authored by 法拉51246's avatar 法拉51246

三个基本功能的新增修改完善,地图当前还不能根据已选择经纬度打开

parent db94161b
...@@ -81,6 +81,33 @@ public class CustomerInfoController { ...@@ -81,6 +81,33 @@ public class CustomerInfoController {
return success(bean); return success(bean);
} }
@GetMapping("/getByCompanyName")
@Operation(summary = "通过公司名称带出基本信息")
@Parameter(name = "companyName", description = "公司名称", required = true, example = "郑州小牛")
public CommonResult<List<CustomerInfoRespVO>> getCustomerInfoByCompanyName(@RequestParam("companyName") String companyName) {
List<CustomerInfoDO> customerInfo = customerInfoService.getCustomerInfoByCompanyName(companyName);
List<CustomerInfoRespVO> bean = BeanUtils.toBean(customerInfo, CustomerInfoRespVO.class);
return success(bean);
}
@GetMapping("/getByPhone")
@Operation(summary = "通过手机号带出基本信息")
@Parameter(name = "companyName", description = "联系方式", required = true, example = "156")
public CommonResult<List<CustomerInfoRespVO>> getCustomerInfoByContact(@RequestParam("contact") String contact) {
List<CustomerInfoDO> customerInfo = customerInfoService.getCustomerInfoByContact(contact);
List<CustomerInfoRespVO> bean = BeanUtils.toBean(customerInfo, CustomerInfoRespVO.class);
return success(bean);
}
@GetMapping("/getAll")
@Operation(summary = "查出所有")
public CommonResult<List<CustomerInfoRespVO>> getAllCustomerInfo() {
List<CustomerInfoDO> customerInfo = customerInfoService.getAllCustomerInfo();
List<CustomerInfoRespVO> bean = BeanUtils.toBean(customerInfo, CustomerInfoRespVO.class);
return success(bean);
}
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得客户信息分页") @Operation(summary = "获得客户信息分页")
@PreAuthorize("@ss.hasPermission('visit:customer-info:query')") @PreAuthorize("@ss.hasPermission('visit:customer-info:query')")
......
...@@ -31,6 +31,9 @@ public class CustomerInfoPageReqVO extends PageParam { ...@@ -31,6 +31,9 @@ public class CustomerInfoPageReqVO extends PageParam {
@Schema(description = "市级行政区编码") @Schema(description = "市级行政区编码")
private String cityCode; private String cityCode;
@Schema(description = "品种名称(多选,逗号分隔)")
private String productNames;
@Schema(description = "创建时间") @Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
......
...@@ -62,9 +62,12 @@ public class CustomerInfoRespVO { ...@@ -62,9 +62,12 @@ public class CustomerInfoRespVO {
private BigDecimal latitude; private BigDecimal latitude;
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("产品ID")
private String productIds; private String productIds;
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("产品名称")
private String productNames;
@Schema(description = "客户所属部门", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "客户所属部门", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("客户所属部门") @ExcelProperty("客户所属部门")
@DictFormat("customer_dept") @DictFormat("customer_dept")
......
...@@ -64,6 +64,9 @@ public class CustomerInfoSaveReqVO { ...@@ -64,6 +64,9 @@ public class CustomerInfoSaveReqVO {
@Schema(description = "产品信息") @Schema(description = "产品信息")
private String productIds; private String productIds;
@Schema(description = "产品信息名称")
private String productNames;
@Schema(description = "客户部门") @Schema(description = "客户部门")
private String department; private String department;
......
...@@ -31,8 +31,8 @@ public class InfoPageReqVO extends PageParam { ...@@ -31,8 +31,8 @@ public class InfoPageReqVO extends PageParam {
private String regionFullName; private String regionFullName;
@Schema(description = "拜访日期") @Schema(description = "拜访日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDate[] visitDate; private LocalDateTime[] visitDate;
@Schema(description = "性质等级", example = "1") @Schema(description = "性质等级", example = "1")
private Integer customerStatus; private Integer customerStatus;
...@@ -40,6 +40,9 @@ public class InfoPageReqVO extends PageParam { ...@@ -40,6 +40,9 @@ public class InfoPageReqVO extends PageParam {
@Schema(description = "拜访品种(多选,逗号分隔)") @Schema(description = "拜访品种(多选,逗号分隔)")
private String visitProductIds; private String visitProductIds;
@Schema(description = "拜访品种名称(多选,逗号分隔)")
private String visitProductNames;
@Schema(description = "拜访方式(字典)") @Schema(description = "拜访方式(字典)")
private Integer visitMethod; private Integer visitMethod;
......
...@@ -64,8 +64,7 @@ public class InfoRespVO { ...@@ -64,8 +64,7 @@ public class InfoRespVO {
@Schema(description = "拜访日期", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "拜访日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("拜访日期") @ExcelProperty("拜访日期")
@JsonFormat(pattern = "yyyy-MM-dd") private LocalDateTime visitDate;
private LocalDate visitDate;
@Schema(description = "性质等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "性质等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "性质等级", converter = DictConvert.class) @ExcelProperty(value = "性质等级", converter = DictConvert.class)
...@@ -73,9 +72,12 @@ public class InfoRespVO { ...@@ -73,9 +72,12 @@ public class InfoRespVO {
private Integer customerStatus; private Integer customerStatus;
@Schema(description = "拜访品种(多选,逗号分隔)") @Schema(description = "拜访品种(多选,逗号分隔)")
@ExcelProperty("拜访品种(多选,逗号分隔)")
private String visitProductIds; private String visitProductIds;
@Schema(description = "拜访品种(多选,逗号分隔)")
@ExcelProperty("拜访品种")
private String visitProductNames;
@Schema(description = "拜访方式(字典)") @Schema(description = "拜访方式(字典)")
@ExcelProperty(value = "拜访方式(字典)", converter = DictConvert.class) @ExcelProperty(value = "拜访方式(字典)", converter = DictConvert.class)
@DictFormat("visit_method") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 @DictFormat("visit_method") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
......
...@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; ...@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import javax.validation.constraints.*; import javax.validation.constraints.*;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -40,6 +41,7 @@ public class InfoSaveReqVO { ...@@ -40,6 +41,7 @@ public class InfoSaveReqVO {
private String areaName; private String areaName;
@Schema(description = "所在地区") @Schema(description = "所在地区")
@NotEmpty(message = "所在地区不能为空")
private String regionFullName; private String regionFullName;
@Schema(description = "定位地址文字描述", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "定位地址文字描述", requiredMode = Schema.RequiredMode.REQUIRED)
...@@ -60,7 +62,7 @@ public class InfoSaveReqVO { ...@@ -60,7 +62,7 @@ public class InfoSaveReqVO {
@Schema(description = "拜访日期", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "拜访日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "拜访日期不能为空") @NotNull(message = "拜访日期不能为空")
private LocalDate visitDate; private LocalDateTime visitDate;
@Schema(description = "性质等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "性质等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "性质等级不能为空") @NotNull(message = "性质等级不能为空")
...@@ -69,6 +71,9 @@ public class InfoSaveReqVO { ...@@ -69,6 +71,9 @@ public class InfoSaveReqVO {
@Schema(description = "拜访品种(多选,逗号分隔)") @Schema(description = "拜访品种(多选,逗号分隔)")
private String visitProductIds; private String visitProductIds;
@Schema(description = "拜访品种名称(多选,逗号分隔)")
private String visitProductNames;
@Schema(description = "拜访方式(字典)") @Schema(description = "拜访方式(字典)")
private Integer visitMethod; private Integer visitMethod;
......
...@@ -95,6 +95,10 @@ public class CustomerInfoDO extends BaseDO { ...@@ -95,6 +95,10 @@ public class CustomerInfoDO extends BaseDO {
* 产品信息 * 产品信息
*/ */
private String productIds; private String productIds;
/**
* 产品信息
*/
private String productNames;
/** /**
* 客户部门 * 客户部门
* *
......
...@@ -90,7 +90,7 @@ public class InfoDO extends BaseDO { ...@@ -90,7 +90,7 @@ public class InfoDO extends BaseDO {
/** /**
* 拜访日期 * 拜访日期
*/ */
private LocalDate visitDate; private LocalDateTime visitDate;
/** /**
* 性质等级 * 性质等级
*/ */
...@@ -99,6 +99,10 @@ public class InfoDO extends BaseDO { ...@@ -99,6 +99,10 @@ public class InfoDO extends BaseDO {
* 拜访品种(多选,逗号分隔) * 拜访品种(多选,逗号分隔)
*/ */
private String visitProductIds; private String visitProductIds;
/**
* 拜访品种(多选,逗号分隔)
*/
private String visitProductNames;
/** /**
* 拜访方式(字典) * 拜访方式(字典)
* *
......
...@@ -28,4 +28,18 @@ public interface CustomerInfoMapper extends BaseMapperX<CustomerInfoDO> { ...@@ -28,4 +28,18 @@ public interface CustomerInfoMapper extends BaseMapperX<CustomerInfoDO> {
.orderByDesc(CustomerInfoDO::getId)); .orderByDesc(CustomerInfoDO::getId));
} }
//根据公司名称查询客户信息(验证是否唯一使用)
default CustomerInfoDO selectByCompanyName(String companyName){
return selectOne(CustomerInfoDO::getCompanyName, companyName);
}
// 根据公司名称或手机号查询(根据任一条件带出符合条件的列表)
default List<CustomerInfoDO> selectListByCompanyName(String companyName) {
return selectList(new LambdaQueryWrapperX<CustomerInfoDO>()
.likeIfPresent(CustomerInfoDO::getCompanyName, companyName));
}
default List<CustomerInfoDO> selectListByContact(String contact) {
return selectList(new LambdaQueryWrapperX<CustomerInfoDO>()
.likeIfPresent(CustomerInfoDO::getContact, contact));
}
} }
\ No newline at end of file
...@@ -52,4 +52,9 @@ public interface CustomerInfoService { ...@@ -52,4 +52,9 @@ public interface CustomerInfoService {
*/ */
PageResult<CustomerInfoDO> getCustomerInfoPage(CustomerInfoPageReqVO pageReqVO); PageResult<CustomerInfoDO> getCustomerInfoPage(CustomerInfoPageReqVO pageReqVO);
List<CustomerInfoDO> getCustomerInfoByCompanyName(String companyName);
List<CustomerInfoDO> getCustomerInfoByContact(String contact);
List<CustomerInfoDO> getAllCustomerInfo();
} }
\ No newline at end of file
...@@ -71,4 +71,18 @@ public class CustomerInfoServiceImpl implements CustomerInfoService { ...@@ -71,4 +71,18 @@ public class CustomerInfoServiceImpl implements CustomerInfoService {
return customerInfoMapper.selectPage(pageReqVO); return customerInfoMapper.selectPage(pageReqVO);
} }
@Override
public List<CustomerInfoDO> getCustomerInfoByCompanyName(String companyName) {
return customerInfoMapper.selectListByCompanyName(companyName);
}
@Override
public List<CustomerInfoDO> getCustomerInfoByContact(String contact) {
return customerInfoMapper.selectListByContact(contact);
}
@Override
public List<CustomerInfoDO> getAllCustomerInfo() {
return customerInfoMapper.selectList();
}
} }
\ No newline at end of file
package cn.iocoder.yudao.module.visit.service.info; package cn.iocoder.yudao.module.visit.service.info;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.visit.controller.admin.info.vo.*;
import cn.iocoder.yudao.module.visit.dal.dataobject.info.InfoDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.visit.controller.admin.customerinfo.vo.CustomerInfoSaveReqVO;
import cn.iocoder.yudao.module.visit.controller.admin.info.vo.InfoPageReqVO;
import cn.iocoder.yudao.module.visit.controller.admin.info.vo.InfoSaveReqVO;
import cn.iocoder.yudao.module.visit.dal.dataobject.customerinfo.CustomerInfoDO;
import cn.iocoder.yudao.module.visit.dal.dataobject.info.InfoDO;
import cn.iocoder.yudao.module.visit.dal.mysql.customerinfo.CustomerInfoMapper;
import cn.iocoder.yudao.module.visit.dal.mysql.info.InfoMapper; import cn.iocoder.yudao.module.visit.dal.mysql.info.InfoMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.visit.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.visit.enums.ErrorCodeConstants.INFO_NOT_EXISTS;
/** /**
* 客户拜访记录 Service 实现类 * 客户拜访记录 Service 实现类
...@@ -29,11 +30,39 @@ public class InfoServiceImpl implements InfoService { ...@@ -29,11 +30,39 @@ public class InfoServiceImpl implements InfoService {
@Resource @Resource
private InfoMapper infoMapper; private InfoMapper infoMapper;
@Resource
private CustomerInfoMapper customerInfoMapper;
@Override @Override
@Transactional(rollbackFor = Exception.class)
public Long createInfo(InfoSaveReqVO createReqVO) { public Long createInfo(InfoSaveReqVO createReqVO) {
// 插入 // 插入
InfoDO info = BeanUtils.toBean(createReqVO, InfoDO.class); InfoDO info = BeanUtils.toBean(createReqVO, InfoDO.class);
infoMapper.insert(info); int insert = infoMapper.insert(info);
if (insert >0){
//拜访记录插入成功,根据【公司名称】判断该客户是否记录在案,如果没有,则插入一条客户信息
CustomerInfoDO customerInfoDO = customerInfoMapper.selectByCompanyName(info.getCompanyName());
if (customerInfoDO == null){
//没查到说明该客户没有记录,插入一条客户信息
CustomerInfoSaveReqVO customerInfoSaveReqVO = new CustomerInfoSaveReqVO();
customerInfoSaveReqVO.setCustomerName(info.getCustomerName());
customerInfoSaveReqVO.setContact(info.getContact());
customerInfoSaveReqVO.setCompanyName(info.getCompanyName());
customerInfoSaveReqVO.setCustomerType(info.getCustomerStatus());
customerInfoSaveReqVO.setProvinceName(info.getProvinceName());
customerInfoSaveReqVO.setCityName(info.getCityName());
customerInfoSaveReqVO.setAreaName(info.getAreaName());
customerInfoSaveReqVO.setRegionFullName(info.getRegionFullName());
customerInfoSaveReqVO.setLocationText(info.getLocationText());
customerInfoSaveReqVO.setLongitude(info.getLongitude());
customerInfoSaveReqVO.setLatitude(info.getLatitude());
customerInfoSaveReqVO.setLocationImage(info.getLocationImage());
customerInfoSaveReqVO.setProductIds(info.getVisitProductIds());
customerInfoSaveReqVO.setProductNames(info.getVisitProductNames());
customerInfoMapper.insert(BeanUtils.toBean(customerInfoSaveReqVO, CustomerInfoDO.class));
}
}
// 返回 // 返回
return info.getId(); return info.getId();
} }
......
...@@ -31,6 +31,20 @@ export const CustomerInfoApi = { ...@@ -31,6 +31,20 @@ export const CustomerInfoApi = {
return await request.get({ url: `/visit/customer-info/get?id=` + id }) return await request.get({ url: `/visit/customer-info/get?id=` + id })
}, },
// 查询客户信息详情根据客户公司名称
getCustomerInfoByCompanyName: async (param: string) => {
return await request.get({ url: `/visit/customer-info/getByCompanyName?companyName=` + param })
},
// 查询客户信息详情根据手机号
getCustomerInfoByPhone: async (param: string) => {
return await request.get({ url: `/visit/customer-info/getByPhone?contact=` + param })
},
// 查询所有客户信息详情
getAll: async () => {
return await request.get({ url: `/visit/customer-info/getAll`})
},
// 查询客户信息中拜访品种详情 // 查询客户信息中拜访品种详情
getProductSimpleList: async (id: number) => { getProductSimpleList: async (id: number) => {
return await request.get({ url: `/visit/customer-info/getProductSimpleList?id=` + id }) return await request.get({ url: `/visit/customer-info/getProductSimpleList?id=` + id })
......
...@@ -140,8 +140,9 @@ watch( ...@@ -140,8 +140,9 @@ watch(
// 防止 val 为字符串、null、undefined 报错 // 防止 val 为字符串、null、undefined 报错
let urls: string[] = [] let urls: string[] = []
//过滤数组中的空字符串
if (Array.isArray(val)) { if (Array.isArray(val)) {
urls = val urls = val.filter((url) => url.trim() !== '')
} else if (typeof val === 'string') { } else if (typeof val === 'string') {
urls = val.split(',').filter((url) => url.trim() !== '') urls = val.split(',').filter((url) => url.trim() !== '')
} }
......
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
<!-- </el-form-item>--> <!-- </el-form-item>-->
<el-form-item label="产品信息" prop="productIds"> <el-form-item label="产品信息" prop="productIds">
<el-input <el-input
v-model="formData.productIds" v-model="formData.productNames"
placeholder="请点击右侧选择" placeholder="请点击右侧选择"
readonly readonly
> >
...@@ -130,6 +130,7 @@ interface CustomerFormData { ...@@ -130,6 +130,7 @@ interface CustomerFormData {
latitude?: number; latitude?: number;
locationImage?: string; locationImage?: string;
productIds?: string; productIds?: string;
productNames?: string;
department?: string; department?: string;
} }
const formData = ref<CustomerFormData>({ const formData = ref<CustomerFormData>({
...@@ -147,6 +148,7 @@ const formData = ref<CustomerFormData>({ ...@@ -147,6 +148,7 @@ const formData = ref<CustomerFormData>({
latitude: undefined, latitude: undefined,
locationImage: undefined, locationImage: undefined,
productIds: undefined, productIds: undefined,
productNames: undefined,
department: undefined, department: undefined,
}) })
const formRules = reactive({ const formRules = reactive({
...@@ -173,10 +175,10 @@ const openProduct=()=>{ ...@@ -173,10 +175,10 @@ const openProduct=()=>{
productListRef.value?.open(); // 调用子组件暴露的方法 productListRef.value?.open(); // 调用子组件暴露的方法
} }
const handleUpdateProduct = (ids: string) => { const handleUpdateProduct = (ids: string,names: string) => {
console.log('来自子组件的产品ID:', ids);
//存入表单 //存入表单
formData.value.productIds = ids; formData.value.productIds = ids;
formData.value.productNames = names;
}; };
//===========================================地图相关操作================================= //===========================================地图相关操作=================================
const mapPickerRef = ref() const mapPickerRef = ref()
...@@ -285,6 +287,7 @@ const resetForm = () => { ...@@ -285,6 +287,7 @@ const resetForm = () => {
latitude: undefined, latitude: undefined,
locationImage: undefined, locationImage: undefined,
productIds: undefined, productIds: undefined,
productNames: undefined,
department: undefined, department: undefined,
} }
formRef.value?.resetFields() formRef.value?.resetFields()
......
...@@ -126,12 +126,13 @@ const props = defineProps({ ...@@ -126,12 +126,13 @@ const props = defineProps({
const tableRef = ref();//表单 const tableRef = ref();//表单
// 定义事件名和参数类型(可选) // 定义事件名和参数类型(可选)
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'updateProduct', data: string): void; (e: 'updateProduct', ids: string, names: string): void;
}>(); }>();
const sendToParent = () => { const sendToParent = () => {
const joinedIds = multipleSelection.value.join(','); // ✅ 转为 "101,203,305" const joinedIds = multipleSelection.value.join(','); // ✅ 转为 "101,203,305"
emit('updateProduct', joinedIds); // ✅ 传 string 给父组件 const joinedNames = multipleSelectionName.value.join(','); // ✅ 转为 "阿莫西林,银翘片"
emit('updateProduct', joinedIds,joinedNames); // ✅ 传 string 给父组件
dialogTableVisible.value = false; // ✅ 关闭弹窗 dialogTableVisible.value = false; // ✅ 关闭弹窗
}; };
...@@ -149,6 +150,7 @@ const queryParams = reactive({ ...@@ -149,6 +150,7 @@ const queryParams = reactive({
}) })
const queryFormRef = ref() // 搜索的表单 const queryFormRef = ref() // 搜索的表单
const multipleSelection = ref<any[]>([]) //存储多选内容 const multipleSelection = ref<any[]>([]) //存储多选内容
const multipleSelectionName = ref<any[]>([]) //存储多选内容
// 打开弹窗 // 打开弹窗
const open = () => { const open = () => {
dialogTableVisible.value = true dialogTableVisible.value = true
...@@ -164,7 +166,10 @@ const open = () => { ...@@ -164,7 +166,10 @@ const open = () => {
/** 多选操作**/ /** 多选操作**/
const handleSelectionChange = (val) => { const handleSelectionChange = (val) => {
multipleSelection.value = val.map(item=>item.id) multipleSelection.value = val.map(item=>item.id)
console.log(val,multipleSelection) multipleSelectionName.value = val.map(item=>item.productName)
console.log(val)
console.log("=========")
console.log(multipleSelectionName)
} }
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
......
...@@ -14,20 +14,15 @@ ...@@ -14,20 +14,15 @@
<el-input v-model="formData.contact" placeholder="请输入联系方式" /> <el-input v-model="formData.contact" placeholder="请输入联系方式" />
</el-form-item> </el-form-item>
<el-form-item label="公司名称" prop="companyName"> <el-form-item label="公司名称" prop="companyName">
<el-input v-model="formData.companyName" placeholder="请输入客户公司名称" /> <el-autocomplete
v-model="formData.companyName"
:fetch-suggestions="querySearch"
clearable
class="inline-input w-50"
@select="handleSelect"
placeholder="请输入客户公司名称"
/>
</el-form-item> </el-form-item>
<!-- <el-form-item label="省名称" prop="provinceName">-->
<!-- <el-input v-model="formData.provinceName" placeholder="请输入省名称" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="市名称" prop="cityName">-->
<!-- <el-input v-model="formData.cityName" placeholder="请输入市名称" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="区名称" prop="areaName">-->
<!-- <el-input v-model="formData.areaName" placeholder="请输入区名称" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="所在地址" prop="areaName">-->
<!-- <el-input v-model="formData.regionFullName" placeholder="请输入区名称" />-->
<!-- </el-form-item>-->
<el-form-item label="所在地区" prop="regionFullName"> <el-form-item label="所在地区" prop="regionFullName">
<el-cascader <el-cascader
placeholder="请选择地区" placeholder="请选择地区"
...@@ -37,18 +32,6 @@ ...@@ -37,18 +32,6 @@
@change="handleChange" @change="handleChange"
/> />
</el-form-item> </el-form-item>
<!-- <el-form-item label="定位地址文字描述" prop="locationText">-->
<!-- <el-input v-model="formData.locationText" placeholder="请输入定位地址文字描述" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="经度" prop="longitude">-->
<!-- <el-input v-model="formData.longitude" placeholder="请输入经度" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="纬度" prop="latitude">-->
<!-- <el-input v-model="formData.latitude" placeholder="请输入纬度" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="定位静态图URL" prop="locationImage">-->
<!-- <UploadImg v-model="formData.locationImage" />-->
<!-- </el-form-item>-->
<el-form-item label="详细地址" prop="locationText"> <el-form-item label="详细地址" prop="locationText">
<el-input <el-input
v-model="formData.locationText" v-model="formData.locationText"
...@@ -64,7 +47,7 @@ ...@@ -64,7 +47,7 @@
<el-form-item label="拜访日期" prop="visitDate"> <el-form-item label="拜访日期" prop="visitDate">
<el-date-picker <el-date-picker
v-model="formData.visitDate" v-model="formData.visitDate"
type="date" type="datetime"
value-format="x" value-format="x"
placeholder="选择拜访日期" placeholder="选择拜访日期"
/> />
...@@ -79,9 +62,9 @@ ...@@ -79,9 +62,9 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="拜访品种" prop="visitProductIds"> <el-form-item label="拜访品种" prop="visitProductNames">
<el-input <el-input
v-model="formData.visitProductIds" v-model="formData.visitProductNames"
placeholder="请点击右侧选择" placeholder="请点击右侧选择"
readonly readonly
> >
...@@ -111,10 +94,24 @@ ...@@ -111,10 +94,24 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="服务内容" prop="serviceContent"> <el-form-item label="服务内容" prop="serviceContent">
<Editor v-model="formData.serviceContent" height="150px" /> <el-input
v-model="formData.serviceContent"
type="textarea"
placeholder="请输入服务内容"
maxlength="500"
show-word-limit
:autosize="{ minRows: 4, maxRows: 6 }"
/>
</el-form-item> </el-form-item>
<el-form-item label="客户反馈" prop="customerFeedback"> <el-form-item label="客户反馈" prop="customerFeedback">
<el-input v-model="formData.customerFeedback" placeholder="请输入客户反馈" /> <el-input
v-model="formData.customerFeedback"
type="textarea"
placeholder="请输入客户反馈"
maxlength="500"
show-word-limit
:autosize="{ minRows: 4, maxRows: 6 }"
/>
</el-form-item> </el-form-item>
<el-form-item label="服务记录图片URL列表" prop="serviceImages"> <el-form-item label="服务记录图片URL列表" prop="serviceImages">
<UploadImgs v-model="formData.serviceImages" :limit="9"/> <UploadImgs v-model="formData.serviceImages" :limit="9"/>
...@@ -130,10 +127,11 @@ ...@@ -130,10 +127,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { InfoApi, InfoVO } from '@/api/visit/info' import { InfoApi, InfoVO } from '@/api/visit/info'
import { CustomerInfoApi } from '@/api/visit/customerinfo'
import productTable from "@/views/visit/customerinfo/productTable.vue"; import productTable from "@/views/visit/customerinfo/productTable.vue";
import { pcaTextArr } from 'element-china-area-data' import { pcaTextArr } from 'element-china-area-data'
import MapPicker from '../util/MapPicker.vue' import MapPicker from '../util/MapPicker.vue'
import dayjs from 'dayjs'; import { onMounted } from 'vue'
/** 客户拜访记录 表单 */ /** 客户拜访记录 表单 */
defineOptions({ name: 'InfoForm' }) defineOptions({ name: 'InfoForm' })
...@@ -159,9 +157,10 @@ const formData = ref({ ...@@ -159,9 +157,10 @@ const formData = ref({
longitude: undefined, longitude: undefined,
latitude: undefined, latitude: undefined,
locationImage: undefined, locationImage: undefined,
visitDate: undefined, visitDate: Date.now(),
customerStatus: undefined, customerStatus: undefined,
visitProductIds: undefined, visitProductIds: undefined,
visitProductNames: undefined,
visitMethod: undefined, visitMethod: undefined,
visitType: undefined, visitType: undefined,
serviceContent: undefined, serviceContent: undefined,
...@@ -182,9 +181,79 @@ const formRules = reactive({ ...@@ -182,9 +181,79 @@ const formRules = reactive({
locationImage: [{ required: true, message: '定位静态图URL不能为空', trigger: 'blur' }], locationImage: [{ required: true, message: '定位静态图URL不能为空', trigger: 'blur' }],
visitDate: [{ required: true, message: '拜访日期不能为空', trigger: 'blur' }], visitDate: [{ required: true, message: '拜访日期不能为空', trigger: 'blur' }],
customerStatus: [{ required: true, message: '性质等级不能为空', trigger: 'blur' }], customerStatus: [{ required: true, message: '性质等级不能为空', trigger: 'blur' }],
serviceContent: [{ required: true, message: '请输入服务内容', trigger: 'blur' }, { max: 500, message: '最多输入 500 个字符', trigger: 'blur' }],
customerFeedback: [{ required: true, message: '请输入客户反馈', trigger: 'blur' }, { max: 500, message: '最多输入 500 个字符', trigger: 'blur' }],
}) })
const formRef = ref() // 表单 Ref const formRef = ref() // 表单 Ref
//===========================================下拉搜索相关====================================
interface RestaurantItem {
companyName: string
contact: string
}
const restaurants = ref<RestaurantItem[]>([])
const querySearch = (queryString: string, cb: any) => {
const results = queryString
? restaurants.value.filter(createFilter(queryString))
: restaurants.value
// call callback function to return suggestions
console.log(results)
cb(results)
}
const createFilter = (queryString: string) => {
return (restaurant: RestaurantItem) => {
return (
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
)
}
}
const loadAll = async () => {
try {
const res = await CustomerInfoApi.getAll()
if (!res || !Array.isArray(res)) {
console.warn('返回结果格式不符合预期:', res)
restaurants.value = []
return
}
restaurants.value = res.map(item => ({
value: item?.companyName || '',
companyName: item?.companyName || '',
contact: item?.contact || '',
customerName: item?.customerName || '',
provinceName: item?.provinceName || '',
cityName: item?.cityName || '',
areaName: item?.areaName || '',
regionFullName: item?.regionFullName || '',
locationText: item?.locationText || '',
longitude: item?.longitude || '',
latitude: item?.latitude || '',
locationImage: item?.locationImage || '',
customerStatus: item?.customerType??'',
}))
} catch (error) {
console.error('加载公司信息失败:', error)
restaurants.value = []
}
}
/** 选中后自动带出公司名称和联系方式 */
const handleSelect = (item: Record<string, any>) => {
formData.value.companyName = item.companyName;
formData.value.contact = item.contact;
formData.value.customerName = item.customerName;
formData.value.regionFullName = item.regionFullName;
formData.value.provinceName = item.provinceName;
formData.value.cityName = item.cityName;
formData.value.areaName = item.areaName;
formData.value.locationText = item.locationText;
formData.value.longitude = item.longitude;
formData.value.latitude = item.latitude;
formData.value.locationImage = item.locationImage;
formData.value.customerStatus = item.customerStatus;
restoreSelectedOptionsFromForm();
}
//===========================================选择产品相关操作================================= //===========================================选择产品相关操作=================================
const productListRef = ref<InstanceType<typeof productTable> | null>(null); // 产品列表 Ref const productListRef = ref<InstanceType<typeof productTable> | null>(null); // 产品列表 Ref
...@@ -193,10 +262,11 @@ const openProduct=()=>{ ...@@ -193,10 +262,11 @@ const openProduct=()=>{
productListRef.value?.open(); // 调用子组件暴露的方法 productListRef.value?.open(); // 调用子组件暴露的方法
} }
const handleUpdateProduct = (ids: string) => { const handleUpdateProduct = (ids: string,names: string) => {
console.log('来自子组件的产品ID:', ids);
//存入表单 //存入表单
formData.value.visitProductIds = ids; formData.value.visitProductIds = ids;
console.log(names)
formData.value.visitProductNames = names;
}; };
//===========================================地图相关操作================================= //===========================================地图相关操作=================================
const mapPickerRef = ref() const mapPickerRef = ref()
...@@ -280,8 +350,6 @@ const submitForm = async () => { ...@@ -280,8 +350,6 @@ const submitForm = async () => {
if (Array.isArray(raw.serviceImages)) { if (Array.isArray(raw.serviceImages)) {
raw.serviceImages = raw.serviceImages.join(','); raw.serviceImages = raw.serviceImages.join(',');
} }
//时间戳转换成字符串
formData.value.visitDate = dayjs(formData.value.visitDate).format('YYYY-MM-DD');
// 提交请求 // 提交请求
formLoading.value = true formLoading.value = true
try { try {
...@@ -316,9 +384,10 @@ const resetForm = () => { ...@@ -316,9 +384,10 @@ const resetForm = () => {
longitude: undefined, longitude: undefined,
latitude: undefined, latitude: undefined,
locationImage: undefined, locationImage: undefined,
visitDate: undefined, visitDate: Date.now(),
customerStatus: undefined, customerStatus: undefined,
visitProductIds: undefined, visitProductIds: undefined,
visitProductNames: undefined,
visitMethod: undefined, visitMethod: undefined,
visitType: undefined, visitType: undefined,
serviceContent: undefined, serviceContent: undefined,
...@@ -328,4 +397,8 @@ const resetForm = () => { ...@@ -328,4 +397,8 @@ const resetForm = () => {
formRef.value?.resetFields() formRef.value?.resetFields()
selectedOptions.value = []; selectedOptions.value = [];
} }
onMounted(() => {
loadAll()
})
</script> </script>
...@@ -135,16 +135,26 @@ ...@@ -135,16 +135,26 @@
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="主键ID" align="center" prop="id" /> <el-table-column label="主键ID" align="center" prop="id" />
<el-table-column label="拜访人姓名" align="center" prop="customerName" width="100px"/> <el-table-column label="拜访人姓名" align="center" prop="customerName" width="100px"/>
<el-table-column label="联系方式" align="center" prop="contact" /> <el-table-column label="联系方式" align="center" prop="contact" width="120px"/>
<el-table-column label="客户公司名称" align="center" prop="companyName" width="120px" /> <el-table-column label="客户公司名称" align="center" prop="companyName" width="160px" />
<el-table-column label="所在省市区" align="center" prop="regionFullName" width="100px" /> <el-table-column label="所在省市区" align="center" prop="regionFullName" width="160px" />
<el-table-column label="拜访日期" align="center" prop="visitDate" /> <el-table-column
label="拜访日期"
align="center"
prop="visitDate"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="性质等级" align="center" prop="customerStatus"> <el-table-column label="性质等级" align="center" prop="customerStatus">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.CUSTOMER_TYPE" :value="scope.row.customerStatus" /> <dict-tag :type="DICT_TYPE.CUSTOMER_TYPE" :value="scope.row.customerStatus" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="拜访品种" align="center" prop="visitProductIds" /> <el-table-column label="拜访品种" align="center" prop="visitProductIds" width="100px">
<template #default="scope">
<ProductList :ids=scope.row.visitProductIds />
</template>
</el-table-column>
<el-table-column label="拜访方式" align="center" prop="visitMethod"> <el-table-column label="拜访方式" align="center" prop="visitMethod">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.VISIT_METHOD" :value="scope.row.visitMethod" /> <dict-tag :type="DICT_TYPE.VISIT_METHOD" :value="scope.row.visitMethod" />
...@@ -162,7 +172,7 @@ ...@@ -162,7 +172,7 @@
:formatter="dateFormatter" :formatter="dateFormatter"
width="180px" width="180px"
/> />
<el-table-column label="操作" align="center" min-width="120px"> <el-table-column label="操作" align="center" min-width="120px" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
link link
...@@ -202,6 +212,7 @@ import { dateFormatter } from '@/utils/formatTime' ...@@ -202,6 +212,7 @@ import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { InfoApi, InfoVO } from '@/api/visit/info' import { InfoApi, InfoVO } from '@/api/visit/info'
import InfoForm from './InfoForm.vue' import InfoForm from './InfoForm.vue'
import ProductList from "@/views/visit/util/ProductList.vue";
/** 客户拜访记录 列表 */ /** 客户拜访记录 列表 */
defineOptions({ name: 'Info' }) defineOptions({ name: 'Info' })
......
...@@ -33,7 +33,6 @@ const gridData = ref<Product[]>([]) ...@@ -33,7 +33,6 @@ const gridData = ref<Product[]>([])
const getHandler = async (): Promise<void> => { const getHandler = async (): Promise<void> => {
try { try {
gridData.value = await ProductApi.getProductByIds(props.ids) // 显式使用props gridData.value = await ProductApi.getProductByIds(props.ids) // 显式使用props
console.log(gridData);
} catch (error) { } catch (error) {
console.error('获取产品失败:', error) console.error('获取产品失败:', error)
gridData.value = [] gridData.value = []
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment