Commit 29054b48 authored by 法拉51246's avatar 法拉51246

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

parent db94161b
......@@ -81,6 +81,33 @@ public class CustomerInfoController {
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")
@Operation(summary = "获得客户信息分页")
@PreAuthorize("@ss.hasPermission('visit:customer-info:query')")
......
......@@ -31,6 +31,9 @@ public class CustomerInfoPageReqVO extends PageParam {
@Schema(description = "市级行政区编码")
private String cityCode;
@Schema(description = "品种名称(多选,逗号分隔)")
private String productNames;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
......
......@@ -62,9 +62,12 @@ public class CustomerInfoRespVO {
private BigDecimal latitude;
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("产品ID")
private String productIds;
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("产品名称")
private String productNames;
@Schema(description = "客户所属部门", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("客户所属部门")
@DictFormat("customer_dept")
......
......@@ -64,6 +64,9 @@ public class CustomerInfoSaveReqVO {
@Schema(description = "产品信息")
private String productIds;
@Schema(description = "产品信息名称")
private String productNames;
@Schema(description = "客户部门")
private String department;
......
......@@ -31,8 +31,8 @@ public class InfoPageReqVO extends PageParam {
private String regionFullName;
@Schema(description = "拜访日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate[] visitDate;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] visitDate;
@Schema(description = "性质等级", example = "1")
private Integer customerStatus;
......@@ -40,6 +40,9 @@ public class InfoPageReqVO extends PageParam {
@Schema(description = "拜访品种(多选,逗号分隔)")
private String visitProductIds;
@Schema(description = "拜访品种名称(多选,逗号分隔)")
private String visitProductNames;
@Schema(description = "拜访方式(字典)")
private Integer visitMethod;
......
......@@ -64,8 +64,7 @@ public class InfoRespVO {
@Schema(description = "拜访日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("拜访日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate visitDate;
private LocalDateTime visitDate;
@Schema(description = "性质等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "性质等级", converter = DictConvert.class)
......@@ -73,9 +72,12 @@ public class InfoRespVO {
private Integer customerStatus;
@Schema(description = "拜访品种(多选,逗号分隔)")
@ExcelProperty("拜访品种(多选,逗号分隔)")
private String visitProductIds;
@Schema(description = "拜访品种(多选,逗号分隔)")
@ExcelProperty("拜访品种")
private String visitProductNames;
@Schema(description = "拜访方式(字典)")
@ExcelProperty(value = "拜访方式(字典)", converter = DictConvert.class)
@DictFormat("visit_method") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
......
......@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import javax.validation.constraints.*;
import java.math.BigDecimal;
......@@ -40,6 +41,7 @@ public class InfoSaveReqVO {
private String areaName;
@Schema(description = "所在地区")
@NotEmpty(message = "所在地区不能为空")
private String regionFullName;
@Schema(description = "定位地址文字描述", requiredMode = Schema.RequiredMode.REQUIRED)
......@@ -60,7 +62,7 @@ public class InfoSaveReqVO {
@Schema(description = "拜访日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "拜访日期不能为空")
private LocalDate visitDate;
private LocalDateTime visitDate;
@Schema(description = "性质等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "性质等级不能为空")
......@@ -69,6 +71,9 @@ public class InfoSaveReqVO {
@Schema(description = "拜访品种(多选,逗号分隔)")
private String visitProductIds;
@Schema(description = "拜访品种名称(多选,逗号分隔)")
private String visitProductNames;
@Schema(description = "拜访方式(字典)")
private Integer visitMethod;
......
......@@ -95,6 +95,10 @@ public class CustomerInfoDO extends BaseDO {
* 产品信息
*/
private String productIds;
/**
* 产品信息
*/
private String productNames;
/**
* 客户部门
*
......
......@@ -90,7 +90,7 @@ public class InfoDO extends BaseDO {
/**
* 拜访日期
*/
private LocalDate visitDate;
private LocalDateTime visitDate;
/**
* 性质等级
*/
......@@ -99,6 +99,10 @@ public class InfoDO extends BaseDO {
* 拜访品种(多选,逗号分隔)
*/
private String visitProductIds;
/**
* 拜访品种(多选,逗号分隔)
*/
private String visitProductNames;
/**
* 拜访方式(字典)
*
......
......@@ -28,4 +28,18 @@ public interface CustomerInfoMapper extends BaseMapperX<CustomerInfoDO> {
.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 {
*/
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 {
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;
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.PageParam;
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 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.module.visit.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.visit.enums.ErrorCodeConstants.INFO_NOT_EXISTS;
/**
* 客户拜访记录 Service 实现类
......@@ -29,11 +30,39 @@ public class InfoServiceImpl implements InfoService {
@Resource
private InfoMapper infoMapper;
@Resource
private CustomerInfoMapper customerInfoMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createInfo(InfoSaveReqVO createReqVO) {
// 插入
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();
}
......
......@@ -31,6 +31,20 @@ export const CustomerInfoApi = {
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) => {
return await request.get({ url: `/visit/customer-info/getProductSimpleList?id=` + id })
......
import request from '@/config/axios'
// 客户拜访记录 VO
export interface InfoVO {
id: number // 主键ID
customerName: string // 客户姓名
contact: string // 联系方式(客户手机号)
companyName: string // 客户公司名称
provinceName: string // 省名称
cityName: string // 市名称
areaName: string // 区名称
locationText: string // 定位地址文字描述
longitude: number // 经度
latitude: number // 纬度
locationImage: string // 定位静态图URL
visitDate: Date // 拜访日期
customerStatus: number // 性质等级
visitProductIds: string // 拜访品种(多选,逗号分隔)
visitMethod: number // 拜访方式(字典)
visitType: number // 拜访类型(字典)
serviceContent: string // 服务内容
customerFeedback: string // 客户反馈
serviceImages: string // 服务记录图片URL列表(JSON数组)
}
// 客户拜访记录 API
export const InfoApi = {
// 查询客户拜访记录分页
getInfoPage: async (params: any) => {
return await request.get({ url: `/visit/info/page`, params })
},
// 查询客户拜访记录详情
getInfo: async (id: number) => {
return await request.get({ url: `/visit/info/get?id=` + id })
},
// 新增客户拜访记录
createInfo: async (data: InfoVO) => {
return await request.post({ url: `/visit/info/create`, data })
},
// 修改客户拜访记录
updateInfo: async (data: InfoVO) => {
return await request.put({ url: `/visit/info/update`, data })
},
// 删除客户拜访记录
deleteInfo: async (id: number) => {
return await request.delete({ url: `/visit/info/delete?id=` + id })
},
// 导出客户拜访记录 Excel
exportInfo: async (params) => {
return await request.download({ url: `/visit/info/export-excel`, params })
},
}
\ No newline at end of file
import request from '@/config/axios'
// 客户拜访记录 VO
export interface InfoVO {
id: number // 主键ID
customerName: string // 客户姓名
contact: string // 联系方式(客户手机号)
companyName: string // 客户公司名称
provinceName: string // 省名称
cityName: string // 市名称
areaName: string // 区名称
locationText: string // 定位地址文字描述
longitude: number // 经度
latitude: number // 纬度
locationImage: string // 定位静态图URL
visitDate: Date // 拜访日期
customerStatus: number // 性质等级
visitProductIds: string // 拜访品种(多选,逗号分隔)
visitMethod: number // 拜访方式(字典)
visitType: number // 拜访类型(字典)
serviceContent: string // 服务内容
customerFeedback: string // 客户反馈
serviceImages: string // 服务记录图片URL列表(JSON数组)
}
// 客户拜访记录 API
export const InfoApi = {
// 查询客户拜访记录分页
getInfoPage: async (params: any) => {
return await request.get({ url: `/visit/info/page`, params })
},
// 查询客户拜访记录详情
getInfo: async (id: number) => {
return await request.get({ url: `/visit/info/get?id=` + id })
},
// 新增客户拜访记录
createInfo: async (data: InfoVO) => {
return await request.post({ url: `/visit/info/create`, data })
},
// 修改客户拜访记录
updateInfo: async (data: InfoVO) => {
return await request.put({ url: `/visit/info/update`, data })
},
// 删除客户拜访记录
deleteInfo: async (id: number) => {
return await request.delete({ url: `/visit/info/delete?id=` + id })
},
// 导出客户拜访记录 Excel
exportInfo: async (params) => {
return await request.download({ url: `/visit/info/export-excel`, params })
},
}
......@@ -140,8 +140,9 @@ watch(
// 防止 val 为字符串、null、undefined 报错
let urls: string[] = []
//过滤数组中的空字符串
if (Array.isArray(val)) {
urls = val
urls = val.filter((url) => url.trim() !== '')
} else if (typeof val === 'string') {
urls = val.split(',').filter((url) => url.trim() !== '')
}
......
......@@ -71,7 +71,7 @@
<!-- </el-form-item>-->
<el-form-item label="产品信息" prop="productIds">
<el-input
v-model="formData.productIds"
v-model="formData.productNames"
placeholder="请点击右侧选择"
readonly
>
......@@ -130,6 +130,7 @@ interface CustomerFormData {
latitude?: number;
locationImage?: string;
productIds?: string;
productNames?: string;
department?: string;
}
const formData = ref<CustomerFormData>({
......@@ -147,6 +148,7 @@ const formData = ref<CustomerFormData>({
latitude: undefined,
locationImage: undefined,
productIds: undefined,
productNames: undefined,
department: undefined,
})
const formRules = reactive({
......@@ -173,10 +175,10 @@ const openProduct=()=>{
productListRef.value?.open(); // 调用子组件暴露的方法
}
const handleUpdateProduct = (ids: string) => {
console.log('来自子组件的产品ID:', ids);
const handleUpdateProduct = (ids: string,names: string) => {
//存入表单
formData.value.productIds = ids;
formData.value.productNames = names;
};
//===========================================地图相关操作=================================
const mapPickerRef = ref()
......@@ -285,6 +287,7 @@ const resetForm = () => {
latitude: undefined,
locationImage: undefined,
productIds: undefined,
productNames: undefined,
department: undefined,
}
formRef.value?.resetFields()
......
......@@ -126,12 +126,13 @@ const props = defineProps({
const tableRef = ref();//表单
// 定义事件名和参数类型(可选)
const emit = defineEmits<{
(e: 'updateProduct', data: string): void;
(e: 'updateProduct', ids: string, names: string): void;
}>();
const sendToParent = () => {
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; // ✅ 关闭弹窗
};
......@@ -149,6 +150,7 @@ const queryParams = reactive({
})
const queryFormRef = ref() // 搜索的表单
const multipleSelection = ref<any[]>([]) //存储多选内容
const multipleSelectionName = ref<any[]>([]) //存储多选内容
// 打开弹窗
const open = () => {
dialogTableVisible.value = true
......@@ -164,7 +166,10 @@ const open = () => {
/** 多选操作**/
const handleSelectionChange = (val) => {
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 () => {
......
......@@ -14,20 +14,15 @@
<el-input v-model="formData.contact" placeholder="请输入联系方式" />
</el-form-item>
<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 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-cascader
placeholder="请选择地区"
......@@ -37,18 +32,6 @@
@change="handleChange"
/>
</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-input
v-model="formData.locationText"
......@@ -64,7 +47,7 @@
<el-form-item label="拜访日期" prop="visitDate">
<el-date-picker
v-model="formData.visitDate"
type="date"
type="datetime"
value-format="x"
placeholder="选择拜访日期"
/>
......@@ -79,9 +62,9 @@
/>
</el-select>
</el-form-item>
<el-form-item label="拜访品种" prop="visitProductIds">
<el-form-item label="拜访品种" prop="visitProductNames">
<el-input
v-model="formData.visitProductIds"
v-model="formData.visitProductNames"
placeholder="请点击右侧选择"
readonly
>
......@@ -111,10 +94,24 @@
</el-select>
</el-form-item>
<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 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 label="服务记录图片URL列表" prop="serviceImages">
<UploadImgs v-model="formData.serviceImages" :limit="9"/>
......@@ -130,10 +127,11 @@
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { InfoApi, InfoVO } from '@/api/visit/info'
import { CustomerInfoApi } from '@/api/visit/customerinfo'
import productTable from "@/views/visit/customerinfo/productTable.vue";
import { pcaTextArr } from 'element-china-area-data'
import MapPicker from '../util/MapPicker.vue'
import dayjs from 'dayjs';
import { onMounted } from 'vue'
/** 客户拜访记录 表单 */
defineOptions({ name: 'InfoForm' })
......@@ -159,9 +157,10 @@ const formData = ref({
longitude: undefined,
latitude: undefined,
locationImage: undefined,
visitDate: undefined,
visitDate: Date.now(),
customerStatus: undefined,
visitProductIds: undefined,
visitProductNames: undefined,
visitMethod: undefined,
visitType: undefined,
serviceContent: undefined,
......@@ -182,9 +181,79 @@ const formRules = reactive({
locationImage: [{ required: true, message: '定位静态图URL不能为空', trigger: 'blur' }],
visitDate: [{ 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
//===========================================下拉搜索相关====================================
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
......@@ -193,10 +262,11 @@ const openProduct=()=>{
productListRef.value?.open(); // 调用子组件暴露的方法
}
const handleUpdateProduct = (ids: string) => {
console.log('来自子组件的产品ID:', ids);
const handleUpdateProduct = (ids: string,names: string) => {
//存入表单
formData.value.visitProductIds = ids;
console.log(names)
formData.value.visitProductNames = names;
};
//===========================================地图相关操作=================================
const mapPickerRef = ref()
......@@ -280,8 +350,6 @@ const submitForm = async () => {
if (Array.isArray(raw.serviceImages)) {
raw.serviceImages = raw.serviceImages.join(',');
}
//时间戳转换成字符串
formData.value.visitDate = dayjs(formData.value.visitDate).format('YYYY-MM-DD');
// 提交请求
formLoading.value = true
try {
......@@ -316,9 +384,10 @@ const resetForm = () => {
longitude: undefined,
latitude: undefined,
locationImage: undefined,
visitDate: undefined,
visitDate: Date.now(),
customerStatus: undefined,
visitProductIds: undefined,
visitProductNames: undefined,
visitMethod: undefined,
visitType: undefined,
serviceContent: undefined,
......@@ -328,4 +397,8 @@ const resetForm = () => {
formRef.value?.resetFields()
selectedOptions.value = [];
}
onMounted(() => {
loadAll()
})
</script>
......@@ -135,16 +135,26 @@
<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="拜访人姓名" align="center" prop="customerName" width="100px"/>
<el-table-column label="联系方式" align="center" prop="contact" />
<el-table-column label="客户公司名称" align="center" prop="companyName" width="120px" />
<el-table-column label="所在省市区" align="center" prop="regionFullName" width="100px" />
<el-table-column label="拜访日期" align="center" prop="visitDate" />
<el-table-column label="联系方式" align="center" prop="contact" width="120px"/>
<el-table-column label="客户公司名称" align="center" prop="companyName" width="160px" />
<el-table-column label="所在省市区" align="center" prop="regionFullName" width="160px" />
<el-table-column
label="拜访日期"
align="center"
prop="visitDate"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="性质等级" align="center" prop="customerStatus">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CUSTOMER_TYPE" :value="scope.row.customerStatus" />
</template>
</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">
<template #default="scope">
<dict-tag :type="DICT_TYPE.VISIT_METHOD" :value="scope.row.visitMethod" />
......@@ -162,7 +172,7 @@
:formatter="dateFormatter"
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">
<el-button
link
......@@ -202,6 +212,7 @@ import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { InfoApi, InfoVO } from '@/api/visit/info'
import InfoForm from './InfoForm.vue'
import ProductList from "@/views/visit/util/ProductList.vue";
/** 客户拜访记录 列表 */
defineOptions({ name: 'Info' })
......
......@@ -33,7 +33,6 @@ const gridData = ref<Product[]>([])
const getHandler = async (): Promise<void> => {
try {
gridData.value = await ProductApi.getProductByIds(props.ids) // 显式使用props
console.log(gridData);
} catch (error) {
console.error('获取产品失败:', error)
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