refactor(archive): 优化列表展示体验,补全客户昵称与添加悬浮提示
1. 前端:为发送人、接收人列添加悬浮提示展示完整ID,移除无用的消息动作列 2. 后端:新增企微客户昵称补全逻辑,实时拉取并更新数据库中缺失的客户名称
This commit is contained in:
parent
75c98d04e6
commit
26fadbe307
@ -1,5 +1,6 @@
|
|||||||
package com.artedu.archive.service;
|
package com.artedu.archive.service;
|
||||||
|
|
||||||
|
import com.artedu.archive.client.WeComApiClient;
|
||||||
import com.artedu.archive.entity.ArchiveMessage;
|
import com.artedu.archive.entity.ArchiveMessage;
|
||||||
import com.artedu.archive.entity.Customer;
|
import com.artedu.archive.entity.Customer;
|
||||||
import com.artedu.archive.entity.Staff;
|
import com.artedu.archive.entity.Staff;
|
||||||
@ -44,6 +45,9 @@ public class ArchiveSessionService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ArchiveMessageMapper archiveMessageMapper;
|
private ArchiveMessageMapper archiveMessageMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WeComApiClient weComApiClient;
|
||||||
|
|
||||||
private static final java.time.format.DateTimeFormatter TIME_FORMATTER =
|
private static final java.time.format.DateTimeFormatter TIME_FORMATTER =
|
||||||
java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
@ -80,9 +84,48 @@ public class ArchiveSessionService {
|
|||||||
|
|
||||||
Page<Customer> pageResult = customerMapper.selectPage(new Page<>(page, size), wrapper);
|
Page<Customer> pageResult = customerMapper.selectPage(new Page<>(page, size), wrapper);
|
||||||
List<CustomerSessionVO> list = pageResult.getRecords().stream().map(this::convertCustomerVO).collect(Collectors.toList());
|
List<CustomerSessionVO> list = pageResult.getRecords().stream().map(this::convertCustomerVO).collect(Collectors.toList());
|
||||||
|
enrichCustomerNames(list);
|
||||||
return PageResult.of(page, size, pageResult.getTotal(), list);
|
return PageResult.of(page, size, pageResult.getTotal(), list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 补全客户昵称:对名字为空或仍为 ID 的外部客户,实时从企微获取并更新数据库
|
||||||
|
*/
|
||||||
|
private void enrichCustomerNames(List<CustomerSessionVO> list) {
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (CustomerSessionVO vo : list) {
|
||||||
|
String customerId = vo.getCustomerId();
|
||||||
|
String name = vo.getName();
|
||||||
|
if (!isExternalUserId(customerId) || (name != null && !name.trim().isEmpty() && !customerId.equals(name))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Map<String, Object> detail = weComApiClient.getExternalContact(customerId);
|
||||||
|
if (detail == null || detail.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Map<String, Object> contact = (Map<String, Object>) detail.get("external_contact");
|
||||||
|
if (contact == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String fetchedName = (String) contact.get("name");
|
||||||
|
if (fetchedName == null || fetchedName.trim().isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vo.setName(fetchedName);
|
||||||
|
Customer customer = customerMapper.selectByCustomerId(customerId, corpId);
|
||||||
|
if (customer != null) {
|
||||||
|
customer.setName(fetchedName);
|
||||||
|
customerMapper.updateById(customer);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("实时获取客户昵称失败: customerId={}", customerId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工的会话列表
|
* 员工的会话列表
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { Table, Input, Select, Tag, Space, Card, Statistic, Row, Col, Button } from 'antd'
|
import { Table, Input, Select, Tag, Space, Card, Statistic, Row, Col, Button, Tooltip } from 'antd'
|
||||||
import { MessageOutlined, FileTextOutlined, PictureOutlined, AudioOutlined, VideoCameraOutlined, FileOutlined, LinkOutlined, EnvironmentOutlined, SmileOutlined, AppstoreOutlined, WechatOutlined } from '@ant-design/icons'
|
import { MessageOutlined, FileTextOutlined, PictureOutlined, AudioOutlined, VideoCameraOutlined, FileOutlined, LinkOutlined, EnvironmentOutlined, SmileOutlined, AppstoreOutlined, WechatOutlined } from '@ant-design/icons'
|
||||||
import request from '../utils/request'
|
import request from '../utils/request'
|
||||||
|
|
||||||
@ -45,12 +45,6 @@ export default function ArchiveList() {
|
|||||||
EXTERNAL: '客户',
|
EXTERNAL: '客户',
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionMap: Record<string, string> = {
|
|
||||||
send: '发送消息',
|
|
||||||
recall: '撤回消息',
|
|
||||||
switch: '切换企业',
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadData = async (page = 1, pageSize = 20) => {
|
const loadData = async (page = 1, pageSize = 20) => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
@ -260,7 +254,9 @@ export default function ArchiveList() {
|
|||||||
dataIndex: 'fromUser',
|
dataIndex: 'fromUser',
|
||||||
width: 120,
|
width: 120,
|
||||||
render: (fromUser: string, record: any) => (
|
render: (fromUser: string, record: any) => (
|
||||||
<span style={{ color: '#333', fontWeight: 500 }}>{record.fromUserName || fromUser}</span>
|
<Tooltip title={fromUser} placement="topLeft">
|
||||||
|
<span style={{ color: '#333', fontWeight: 500 }}>{record.fromUserName || fromUser}</span>
|
||||||
|
</Tooltip>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -280,23 +276,20 @@ export default function ArchiveList() {
|
|||||||
width: 160,
|
width: 160,
|
||||||
render: (time: string) => <span style={{ color: '#666', fontSize: 13 }}>{time}</span>,
|
render: (time: string) => <span style={{ color: '#666', fontSize: 13 }}>{time}</span>,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '消息动作',
|
|
||||||
dataIndex: 'action',
|
|
||||||
width: 90,
|
|
||||||
align: 'center' as const,
|
|
||||||
render: (action: string) => <span style={{ color: '#666' }}>{actionMap[action] || action}</span>,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '接收人',
|
title: '接收人',
|
||||||
dataIndex: 'toUser',
|
dataIndex: 'toUser',
|
||||||
width: 200,
|
width: 200,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (_: any, record: any) => (
|
render: (_: any, record: any) => {
|
||||||
<span style={{ color: '#666', fontSize: 13 }} title={parseReceivers(record.toUser, record.tolist)}>
|
const ids = parseReceivers(record.toUser, record.tolist)
|
||||||
{parseReceivers(record.toUser, record.tolist)}
|
const names = record.toUserName || ids
|
||||||
</span>
|
return (
|
||||||
),
|
<Tooltip title={ids} placement="topLeft">
|
||||||
|
<span style={{ color: '#666', fontSize: 13 }}>{names}</span>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user