提交 682cdc31 作者: ZhangLingKun

功能:消息管理-客服消息

上级 fea29bda
流水线 #9023 已通过 于阶段
in 1 分 4 秒
......@@ -188,3 +188,97 @@ export type getMessageType = InterFunction<
dynamicMessage: number;
}
>;
// 获取用户信息
export type UserInfoType = {
accountStatus: number;
accountType: number;
companyAuthStatus: number;
email: string;
id: number;
nickName: string;
phoneNum: string;
portType: number;
source: number;
uid: string;
userImg: string;
userName: string;
userSex: number;
realNameAuthStatus: number;
auditStatus: number;
totalPoints: number;
xzAuthStatus: number;
cooperationTagVOS: {
createTime: string;
id: number;
tagDescription: string;
tagImg: string;
tagName: string;
tagRequire: string;
}[];
coverPicture: string;
districtChildId: number;
region: string;
briefIntroduction: string;
companyInfoVO: {
address: string;
backImg: string;
backUserAccountId: number;
brandLogo: string;
brandName: string;
companyName: string;
companyType: number;
companyUserName: string;
content: string;
creditCode: string;
distance: number;
fullName: string;
id: number;
lat: number;
leader: number;
licenseImg: string;
lon: number;
phoneNum: number;
remark: string;
score: string;
userAccountId: number;
};
userRcdVO: {
createTime: string;
id: number;
rcdNickname: string;
rcdUserId: number;
rcdUserName: string;
remark: string;
userAccountId: number;
};
userStateVO: {
icon: string;
id: number;
state: string;
};
pilotJoinCompanyInfoVO: {
address: string;
backImg: string;
backUserAccountId: number;
backUserId: number;
brandLogo: string;
brandName: string;
companyName: string;
companyType: number;
companyUserName: string;
content: string;
creditCode: string;
distance: number;
fullName: string;
id: number;
lat: number;
leader: number;
licenseImg: string;
lon: number;
phoneNum: number;
profileUrl: string;
remark: string;
score: string;
userAccountId: number;
};
};
import { InterFunction, InterItemFunction, InterListFunction } from '~/api/interface';
import { UserInfoType } from '~/api/interface/commonType';
// 账号-列表
export type listBAccountPageType = InterListFunction<
{
......@@ -368,3 +369,112 @@ export type getRolesListType = InterFunction<
roleName: string;
}[]
>;
// 根据公司id获取用户id和角色信息
export type listUserAndRoleByCompanyIdType = InterFunction<
{
companyInfoId?: number;
},
{
/**
* 角色id
*/
roleId: number;
/**
* 角色姓名
*/
roleName: string;
/**
* 绑定用户id
*/
userAccountId: number;
userAccountVO: UserInfoType;
}[]
>;
// 用户信息列表
export type selectUserListType = InterFunction<
{ userAccountId?: number },
{
nickName: string;
phoneNum: string;
unreadCount: number;
userAccountId: number;
userImg: string;
userName: null;
endMessage: string;
createTime: string;
companyInfoVO?: {
address: string;
brandLogo: string;
brandName: string;
companyName: string;
companyType: number;
companyUserName: string;
content: string;
creditCode: string;
fullName: string;
id: number;
lat: number;
leader: number;
licenseImg: string;
lon: number;
phoneNum: string;
remark: string;
score: string;
userAccountId: number;
province: string;
city: string;
backUserId: number;
companyBindUserId: number;
};
}[]
>;
// 用户聊天详细信息
export type selectUserMessageType = InterListFunction<
{
receiverUserId: number;
backUserId?: number;
sendUserId?: number;
},
{
content: string;
createTime: string;
id: number;
imgUrl: null;
receiverUserId: number;
senderUserId: number;
backUserId: number | null;
}
>;
// 用户发送消息
export type insertUserMessageType = InterListFunction<
{
/**
* 消息内容
*/
content?: string;
/**
* 发送的图片
*/
imgUrl?: string;
/**
* 接收方用户ID
*/
receiverUserId: number;
backUserId?: number;
sendUserId?: number;
},
NonNullable<unknown>
>;
// 用户——系统消息列表
export type systemMessageListByUserType = InterListFunction<
{
id?: number;
},
{
content: string;
createTime: string;
id: number;
read: boolean;
subject: string;
}
>;
......@@ -11,6 +11,7 @@ import {
getUserAddressInfoType,
insertBAccountType,
insertRoleInfoType,
insertUserMessageType,
listBAccountPageType,
listCompanyAdd,
listCompanyMembersType,
......@@ -20,7 +21,11 @@ import {
listMenuInfoType,
listRoleInfoPageType,
listRoleMenuInfoType,
listUserAndRoleByCompanyIdType,
removeBAccountType,
selectUserListType,
selectUserMessageType,
systemMessageListByUserType,
transferLeaderType,
unbindCompanyMemberType,
updateBAccountType,
......@@ -128,4 +133,24 @@ export class SystemManageAPI {
// 获取角色列表
static getRolesList: getRolesListType = (params) =>
axios.get('/userapp/user-account/getRolesList', { params });
// 根据公司id获取用户id和角色信息
static listUserAndRoleByCompanyId: listUserAndRoleByCompanyIdType = (params) =>
axios.get('/userapp/company/listUserAndRoleByCompanyId', { params });
// 用户信息列表
static selectUserList: selectUserListType = (params) =>
axios.get('/userapp/message/selectUserList', { params });
// 用户聊天详细信息
static selectUserMessage: selectUserMessageType = (params) =>
axios.post('/userapp/message/selectUserMessage', params);
// 用户发送消息
static insertUserMessage: insertUserMessageType = (params) =>
axios.post('/userapp/message/insertUserMessage', params);
// 用户——系统消息列表
static systemMessageListByUser: systemMessageListByUserType = (params) =>
axios.post('/userapp/message/systemMessageListByUser', params);
}
import React, { useEffect, useState } from 'react';
import { App } from 'antd';
import { CommonAPI } from '~/api';
const QrcodeView: React.FC<{
path?: string;
scene?: string;
}> = ({ path = 'pages/welcome/index', scene = 'type=share' }) => {
// 消息钩子
const { message } = App.useApp();
// 二维码的地址
const [qrCodeData, setQrCodeData] = useState<string>();
// 获取二维码
const getQrcodeLogin = async () => {
// 获取二维码
const res = await CommonAPI.getAppletQRCode({
page: path || 'pages/welcome/index',
scene: scene || 'type=share',
});
if (res && res.code === '200') {
if (!res.result) {
message.warning('获取登录二维码失败');
return;
}
// 设置当前登录的二维码
setQrCodeData(`data:image/png;base64,${res.result}`);
}
};
// 组件挂载
useEffect(() => {
if (!path) return;
getQrcodeLogin().then();
}, [path]);
return (
<img
className='animate__animated animate__faster animate__fadeIn'
src={qrCodeData}
alt='云享飞小程序'
style={{ width: '100%', height: '100%' }}
/>
);
};
export default QrcodeView;
......@@ -6,6 +6,7 @@ import Viewer from '~/components/viewer';
import saveAs from 'file-saver';
import { fileTypeList } from '~/utils/dictionary';
export type FileUploadProps = PropsType;
interface PropsType {
listType?: 'text' | 'picture' | 'picture-card'; // 上传列表的内建样式
fileSize?: number; // 文件大小
......@@ -23,6 +24,7 @@ interface PropsType {
) => void; // 上传文件改变时的状态
defaultFileList?: { url: string }[]; // 默认文件列表
disabled?: boolean; // 是否禁用
showUploadList?: boolean;
}
export const Uploader: React.FC<PropsType> = (props) => {
Uploader.defaultProps = {
......@@ -32,6 +34,7 @@ export const Uploader: React.FC<PropsType> = (props) => {
fileType: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'],
defaultFileList: [],
disabled: false,
showUploadList: true,
};
const {
fileType = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'],
......@@ -154,7 +157,12 @@ export const Uploader: React.FC<PropsType> = (props) => {
<div className='uploader-view'>
{listType === 'text' ? (
<>
<Upload {...uploadProps} style={{ width: '100%' }} disabled={disabled || uploading}>
<Upload
{...uploadProps}
style={{ width: '100%' }}
disabled={disabled || uploading}
showUploadList={props?.showUploadList}
>
<>{fileList.length < (fileLength || 1) && children}</>
</Upload>
{progress > 0 && uploading && (
......
import React, { useState } from 'react';
import { PictureOutlined } from '@ant-design/icons';
import { InterDataType, InterReqType } from '~/api/interface';
import { insertUserMessageType, selectUserListType } from '~/api/interface/systemManageType';
import { FileUploadProps, Uploader } from '~/components/uploader';
import { SystemManageAPI } from '~/api';
import { Button, Input, message } from 'antd';
// 当前消息类型
type DataType = InterDataType<selectUserListType>;
// 请求类型
type ReqType = Omit<InterReqType<insertUserMessageType>, 'receiverUserId'>;
const MessageChatActionView: React.FC<{
currentData: DataType[0];
userAccountId: number;
onRefresh: () => void;
}> = ({ currentData, userAccountId, onRefresh }) => {
// 消息数据
const [messageValue, setMessageValue] = useState<string>();
// 提交数据
const handleSubmit = async (data?: ReqType) => {
if (!messageValue && !data?.imgUrl) {
await message.warning('请输入内容');
return;
}
if (currentData?.userAccountId === userAccountId) {
await message.warning('不能给自己发送消息');
return;
}
const res = await SystemManageAPI.insertUserMessage({
content: messageValue,
receiverUserId: currentData?.userAccountId,
backUserId: currentData?.companyInfoVO?.backUserId,
sendUserId: userAccountId,
...data,
});
if (res && res.code === '200') {
setMessageValue(undefined);
await message.success('发送成功');
// 刷新数据
onRefresh?.();
}
};
// 上传图片回调
const handleUploadImage: FileUploadProps['onChange'] = async (res) => {
await handleSubmit({
imgUrl: JSON.stringify([res?.at(-1)?.url]),
});
};
return (
<div className='message-chat-action'>
<div className='action-head'>
<Uploader
fileUpload
listType='text'
fileLength={6}
fileSize={50}
showUploadList={false}
onChange={handleUploadImage}
>
<PictureOutlined style={{ fontSize: 20, color: '#777' }} />
</Uploader>
</div>
<div className='action-input'>
<Input.TextArea
value={messageValue}
maxLength={200}
placeholder='请输入消息,点击发送按钮发送'
showCount
rows={4}
onChange={(e) => setMessageValue(e.target.value)}
// placeholder='请输入消息,按Enter键 或 点击发送按钮发送'
/>
</div>
<div className='action-button flex-end'>
<Button type={'primary'} onClick={() => handleSubmit()}>
发送
</Button>
</div>
</div>
);
};
export default MessageChatActionView;
import React, { useEffect, useState } from 'react';
import { InterDataType, InterListType } from '~/api/interface';
import { selectUserListType, selectUserMessageType } from '~/api/interface/systemManageType';
import { SystemManageAPI } from '~/api';
import MessageChatActionView from '~/pages/messageManage/messageChat/comp/messageChatAction';
import { Image } from 'antd';
// 当前消息类型
type DataType = InterDataType<selectUserListType>;
// 列表类型
type ListType = InterListType<selectUserMessageType>;
const MessageChatContentView: React.FC<{ currentData: DataType[0]; userAccountId: number }> = ({
currentData,
userAccountId,
}) => {
// 消息列表
const [messageList, setMessageList] = useState<ListType>();
// 获取用户头像
const getUserContentShow = () => {
const { companyInfoVO, userAccountId, userImg, userName, nickName } = currentData;
// 用户对商家聊天
if (companyInfoVO?.id && companyInfoVO?.companyBindUserId === userAccountId) {
return {
icon: `${companyInfoVO?.brandLogo}?x-oss-process=image/quality,q_25`,
name: companyInfoVO?.brandName || companyInfoVO?.companyName || '与商家的聊天',
};
}
// 商家对用户聊天
if (companyInfoVO?.id && companyInfoVO?.companyBindUserId !== userAccountId) {
return {
icon: `${userImg}?x-oss-process=image/quality,q_25`,
name: nickName || userName || '与用户的聊天',
};
}
// 用户对用户聊天
return {
icon: `${userImg}?x-oss-process=image/quality,q_25`,
name: nickName || userName || '与用户的聊天',
};
};
// 获取当前对话列表
const getMessageList = async () => {
const res = await SystemManageAPI.selectUserMessage({
pageNo: 1,
pageSize: 9999,
receiverUserId: currentData?.userAccountId,
backUserId: currentData?.companyInfoVO?.backUserId,
sendUserId: userAccountId,
});
if (res && res.code === '200') {
setMessageList(res.result?.list?.reverse() || []);
// console.log('对话列表 --->', currentData);
}
};
// 转换图片数据
const getImgUrlList = (data: ListType[0]): string[] => {
if (data?.imgUrl) {
try {
return JSON.parse(data?.imgUrl);
} catch (e) {
return ['https://file.iuav.com/file/error.png'];
}
} else {
return [];
}
};
// 组件挂载
useEffect(() => {
if (!currentData?.userAccountId) return;
getMessageList().then();
}, [currentData]);
// 消息列表副作用
useEffect(() => {
if (!messageList?.length) return;
const contentScroll: any = document.querySelector('.content-scroll');
const contentList: any = document.querySelector('.content-scroll .content-list');
if (contentList?.offsetHeight > contentScroll?.offsetHeight) {
setTimeout(() => {
contentScroll.scrollTop = contentList.scrollHeight;
}, 500);
}
}, [messageList]);
return (
<div className='message-chat-content-view'>
<div className='content-head flex-start'>
<img className='image' src={getUserContentShow()?.icon} alt={getUserContentShow()?.name} />
<div className='title'>{getUserContentShow()?.name}</div>
</div>
<div className='content-scroll'>
<div className='content-list'>
{messageList?.map((i, j) => (
<div className='list-item flex-center' key={j}>
<div className='item-date'>{i?.createTime}</div>
<div
className={`item-content ${
i?.senderUserId !== userAccountId ? 'flex-start' : 'flex-end'
}`}
>
<div className='detail'>
{i?.content && <div className='text'>{i?.content}</div>}
{getImgUrlList(i)?.length > 0 &&
getImgUrlList(i)?.map((n, m) => <Image key={m} src={n} width={200} />)}
</div>
</div>
</div>
))}
</div>
</div>
<MessageChatActionView
currentData={currentData}
userAccountId={userAccountId}
onRefresh={getMessageList}
/>
</div>
);
};
export default MessageChatContentView;
import React, { useEffect, useState } from 'react';
import { InterDataType, InterListType } from '~/api/interface';
import { selectUserListType, systemMessageListByUserType } from '~/api/interface/systemManageType';
import { transDateStr } from '~/utils';
import { isArray } from 'lodash';
import { SystemManageAPI } from '~/api';
// 消息类型
type MessageType = InterDataType<selectUserListType>;
const MessageChatListView: React.FC<{
messageList: MessageType;
current: number;
isSystem: boolean;
onSelect: (j: number) => void;
onSystem: () => void;
}> = ({ messageList, current, isSystem, onSelect, onSystem }) => {
// 获取消息展示信息
const getMessageShow = (data: MessageType[0]) => {
// console.log('展示信息 --->', props.detail)
const { companyInfoVO, userAccountId, userImg, nickName, userName } = data;
// 用户对商家聊天
if (companyInfoVO?.id && companyInfoVO?.companyBindUserId === userAccountId) {
return {
icon: `${companyInfoVO?.brandLogo}?x-oss-process=image/quality,q_25`,
name: companyInfoVO?.brandName || companyInfoVO?.companyName || '与商家的聊天',
label: true,
labelText: '商家客服',
};
}
// 商家对用户聊天
if (companyInfoVO?.id && companyInfoVO?.companyBindUserId !== userAccountId) {
return {
icon: `${userImg}?x-oss-process=image/quality,q_25`,
name: nickName || userName || '与用户的聊天',
label: true,
labelText: '客服消息',
};
}
// 用户对用户聊天
return {
icon: `${userImg}?x-oss-process=image/quality,q_25`,
name: nickName || userName || '与用户的聊天',
label: false,
labelText: undefined,
};
};
// 获取最后一条消息
const getEndMessage = (data: MessageType[0]) => {
try {
return isArray(JSON.parse(data?.endMessage)) ? '[图片]' : data?.endMessage;
} catch (error) {
return data?.endMessage || '[其他消息]';
}
};
// 系统消息列表
const [systemList, setSystemList] = useState<InterListType<systemMessageListByUserType>>();
// 获取系统消息列表
const getSystemList = async () => {
const res = await SystemManageAPI.systemMessageListByUser({
pageNo: 1,
pageSize: 1,
});
if (res && res.code === '200') {
setSystemList(res.result?.list || []);
}
};
// 组件挂载
useEffect(() => {
getSystemList().then();
}, []);
return (
<div className='message-chat-list'>
<div
className={`list-item flex-start ${isSystem && 'item-active'}`}
onClick={() => onSystem?.()}
>
<img
className='item-image'
src={`https://file.iuav.com/file/sharefly-message-sys-icon.png`}
alt='用户头像'
/>
<div className='item-content'>
<div className='title text-ellipsis'>系统消息</div>
<div className='text text-ellipsis'>{systemList?.[0]?.subject}</div>
</div>
<div className='item-time'>{transDateStr(systemList?.[0]?.createTime)}</div>
</div>
{messageList?.map((i, j) => (
<div
className={`list-item flex-start ${current === j && !isSystem && 'item-active'}`}
key={j}
onClick={() => onSelect?.(j)}
>
<img className='item-image' src={getMessageShow(i)?.icon} alt='用户头像' />
<div className='item-content'>
<div className='title text-ellipsis flex-start'>
<view>{getMessageShow(i)?.name}</view>
{getMessageShow(i)?.label && (
<div className='label'>{getMessageShow(i)?.labelText}</div>
)}
</div>
<div className='text flex-between'>
<div className='text text-ellipsis'>
{!i?.unreadCount ? getEndMessage(i) : `你有${i?.unreadCount}条消息未读`}
</div>
{i?.unreadCount ? <div className='tag'>{i?.unreadCount}</div> : null}
</div>
</div>
<div className='item-time'>{transDateStr(i?.createTime)}</div>
</div>
))}
</div>
);
};
export default MessageChatListView;
import { useEffect, useState } from 'react';
import { InterListType } from '~/api/interface';
import { systemMessageListByUserType } from '~/api/interface/systemManageType';
import { SystemManageAPI } from '~/api';
const MessageChatSystemView = () => {
// 系统消息列表
const [systemList, setSystemList] = useState<InterListType<systemMessageListByUserType>>();
// 获取系统消息列表
const getSystemList = async () => {
const res = await SystemManageAPI.systemMessageListByUser({
pageNo: 1,
pageSize: 9999,
});
if (res && res.code === '200') {
setSystemList(res.result?.list?.reverse() || []);
}
};
// 组件挂载
useEffect(() => {
getSystemList().then();
}, []);
// 消息列表副作用
useEffect(() => {
if (!systemList?.length) return;
const contentScroll: any = document.querySelector('.content-scroll');
const contentList: any = document.querySelector('.content-scroll .content-list');
if (contentList?.offsetHeight > contentScroll?.offsetHeight) {
setTimeout(() => {
contentScroll.scrollTop = contentList.scrollHeight;
}, 500);
}
}, [systemList]);
return (
<div className='message-chat-content-view'>
<div className='content-head flex-start'>
<img
className='image'
src={'https://file.iuav.com/file/sharefly-message-sys-icon.png'}
alt={'系统消息'}
/>
<div className='title'>系统消息</div>
</div>
<div className='content-scroll' style={{ minHeight: '74vh', border: 'none' }}>
<div className='content-list'>
{systemList?.map((i, j) => (
<div className='list-item flex-center' key={j}>
<div className='item-date'>{i?.createTime}</div>
<div className={`item-content flex-start`}>
<div className='detail'>
<div className='text'>{i?.subject}</div>
{i?.content && (
<div className='text' dangerouslySetInnerHTML={{ __html: i?.content }}></div>
)}
</div>
</div>
</div>
))}
</div>
</div>
</div>
);
};
export default MessageChatSystemView;
.message-chat {
position: relative;
min-width: 1100px;
box-sizing: border-box;
align-items: flex-start !important;
&-list {
position: relative;
width: 300px;
height: 82vh;
//background: lightcoral;
box-sizing: border-box;
padding: 0 5px;
overflow-y: scroll;
overflow-x: hidden;
.list-item {
position: relative;
width: 100%;
box-sizing: border-box;
padding: 10px;
border-radius: 8px;
cursor: pointer;
&:hover {
background: rgba(233, 240, 254, 0.35);
}
.item-image {
width: 45px;
height: 45px;
border-radius: 50%;
margin-right: 8px;
}
.item-content {
position: relative;
width: 200px;
.title {
width: 100%;
color: #000000;
font-weight: bold;
margin-bottom: 8px;
}
.text {
position: relative;
width: 100%;
box-sizing: border-box;
color: #666666;
font-size: 11px;
.text{
width: 150px;
color: #666666;
font-size: 11px;
}
.tag{
background: #FF2741;
border-radius: 20px;
text-align: center;
line-height: 16px;
box-sizing: border-box;
padding: 0 6px;
font-size: 12px;
font-weight: 500;
color: #FFFFFF;
transform: scale(0.8) translateX(20px);
}
}
.label {
position: relative;
box-sizing: border-box;
height: 16px;
background: linear-gradient(270deg, #fff1ec 0%, #ffffff 54%, #ffe5db 100%);
border-radius: 4px;
border: 1px solid #ffb099;
padding: 0 4px;
line-height: 14px;
text-align: center;
font-weight: 500;
font-size: 10px;
color: #ff521e;
margin-left: 8px;
}
}
.item-time {
position: absolute;
top: 18px;
right: 10px;
text-align: right;
color: #666666;
font-size: 11px;
}
}
.item-active {
background: #E9F0FE;
&:hover {
background: #E9F0FE;
}
}
}
&-content {
position: relative;
width: 70rem;
min-height: 80vh;
background: #F6F6F6;
box-sizing: border-box;
margin: 0 10px 0 5px;
border-radius: 8px;
overflow: hidden;
&-view {
position: relative;
width: 100%;
box-sizing: border-box;
.content-head {
position: relative;
box-sizing: border-box;
padding: 10px 10px;
border-bottom: 0.5px #CBCBCB solid;
.image {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
}
.title {
color: #000000;
font-weight: bold;
}
}
.content-scroll {
position: relative;
width: 100%;
height: 53vh;
box-sizing: border-box;
//background: lightsalmon;
overflow-y: scroll;
overflow-x: hidden;
border-bottom: 0.5px #CBCBCB solid;
.content-list {
position: relative;
width: 100%;
box-sizing: border-box;
//background: lightblue;
padding: 20px 0;
.list-item {
position: relative;
width: 100%;
box-sizing: border-box;
flex-direction: column;
.item-date {
font-weight: 400;
font-size: 12px;
color: #999999;
margin-bottom: 16px;
}
.item-content {
position: relative;
width: 100%;
box-sizing: border-box;
margin-bottom: 16px;
padding: 0 12px;
.detail {
position: relative;
box-sizing: border-box;
max-width: 400px;
width: auto;
background: #E8E8E9;
border-radius: 4px;
padding: 8px 12px;
font-size: 14px;
color: #333333;
line-height: 16px;
}
}
}
}
}
}
}
&-action {
position: relative;
width: 100%;
box-sizing: border-box;
padding: 6px 10px;
.action-head{
position: relative;
width: 100%;
box-sizing: border-box;
font-size: 20px;
color: #777777;
}
.action-input{
position: relative;
width: 100%;
box-sizing: border-box;
margin-bottom: 20px;
}
}
&-qrcode {
position: relative;
width: 200px;
box-sizing: border-box;
padding: 30px 0 0 0;
.qrcode-view{
position: relative;
width: 140px;
box-sizing: border-box;
margin: 0 auto;
}
.qrcode-text{
width: 100%;
font-weight: 400;
font-size: 14px;
color: #666666;
text-align: center;
margin-top: 30px;
}
}
}
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import './index.scss';
import MessageChatListView from '~/pages/messageManage/messageChat/comp/messageChatList';
import { SystemManageAPI } from '~/api';
import { isNull } from 'lodash';
import { InterDataType } from '~/api/interface';
import { selectUserListType } from '~/api/interface/systemManageType';
import MessageChatContentView from 'src/pages/messageManage/messageChat/comp/messageChatContent';
import QrcodeView from '~/components/qrcodeView';
import MessageChatSystemView from '~/pages/messageManage/messageChat/comp/messageChatSystem';
// 消息类型
type MessageType = InterDataType<selectUserListType>;
const MessageChatPage: React.FC = () => {
// 登录的用户信息
const { userInfo } = useSelector((state: any) => state.UserInfo);
// 用户id
const [userAccountId, setUserAccountId] = useState<number>();
// 获取用户id
const getUserAccountId = async () => {
const res = await SystemManageAPI.listUserAndRoleByCompanyId({
companyInfoId: userInfo?.companyInfoVO?.id,
});
if (res && res.code === '200') {
if (res.result?.[0]?.userAccountId) {
setUserAccountId(res.result?.[0]?.userAccountId);
} else {
// message.error('获取用户id失败');
setIsSystem(true);
}
// console.log('获取用户id --->', res);
// setUserAccountId(3);
}
};
// 当前是否是系统消息
const [isSystem, setIsSystem] = useState<boolean>(false);
// 当前选择的消息
const [currentIndex, setCurrentIndex] = useState<number>(0);
// 用户消息列表
const [messageList, setMessageList] = useState<MessageType>([]);
// 获取用户消息列表
const getMessageList = async () => {
const res = await SystemManageAPI.selectUserList({
userAccountId: userAccountId,
// userAccountId: 3,
});
if (res && res.code === '200') {
setMessageList(res.result || []);
}
};
// 二维码路由参数
const qrcodePathQueryList = [
{
id: 1,
path: 'page-product/product-store/index',
scene: `?id=${messageList[currentIndex]?.companyInfoVO?.backUserId}`,
},
{
id: 3,
path: 'page-rent/rent-store/index',
scene: `?id=${messageList[currentIndex]?.companyInfoVO?.backUserId}`,
},
{
id: 4,
path: 'page-flyer/institution-detail/index',
scene: `?id=${messageList[currentIndex]?.companyInfoVO?.backUserId}`,
},
{
id: 5,
path: 'page-service/service-store/index',
scene: `?id=${messageList[currentIndex]?.companyInfoVO?.id}`,
},
];
// 获取二维码路由参数
const getQrcodePathQuery = () => {
const tagId = userInfo?.companyInfoVO?.cooperationTagId;
if (!tagId) return;
return qrcodePathQueryList?.find((i) => i?.id === tagId);
};
// 组件挂载
useEffect(() => {
// console.log('组件挂载 --->', userInfo);
if (!userInfo?.appUserAccountId) {
getUserAccountId().then();
} else {
setUserAccountId(userInfo?.appUserAccountId);
}
}, []);
// 用户id副作用
useEffect(() => {
if (isNull(userAccountId)) return;
getMessageList().then();
}, [userAccountId]);
return (
<div className='message-chat flex-start'>
<MessageChatListView
messageList={messageList}
current={currentIndex}
isSystem={isSystem}
onSelect={(index) => {
setCurrentIndex(index);
setIsSystem(false);
}}
onSystem={() => setIsSystem(true)}
/>
<div className='message-chat-content'>
{messageList?.[currentIndex] && !!userAccountId && !isSystem ? (
<MessageChatContentView
currentData={messageList[currentIndex]}
userAccountId={userAccountId}
/>
) : null}
{isSystem ? <MessageChatSystemView /> : null}
</div>
<div className='message-chat-qrcode'>
<div className='qrcode-view'>
{getQrcodePathQuery()?.id ? (
<QrcodeView path={getQrcodePathQuery()?.path} scene={getQrcodePathQuery()?.scene} />
) : null}
</div>
<div className='qrcode-text'>扫码进入小程序店铺</div>
</div>
</div>
);
};
export default MessageChatPage;
......@@ -178,6 +178,7 @@ import CustomApplyPage from '~/pages/customManage/customApply';
import StoreDecoratePage from '~/pages/resourceManage/storeDecorate';
import PointExchangeGoodsPage from '~/pages/activityManage/pointExchangeGoods';
import PointExchangeListPage from '~/pages/activityManage/pointExchangeList';
import MessageChatPage from '~/pages/messageManage/messageChat';
const AddressManageView = React.lazy(() => import('~/pages/systemManage/addressManage'));
// const IndustryListView = React.lazy(() => import('~/pages/mallManage/industryManage/industryList')); //行业列表
......@@ -1453,4 +1454,28 @@ export const routerList: Array<RouteObjectType> = [
},
],
},
{
path: '/messageManage',
element: <LayoutView />,
errorElement: <ErrorPage />,
meta: {
id: 1400,
icon: <CommentOutlined />,
title: '消息管理',
develop: true,
},
children: [
{
path: '/messageManage/messageChat',
element: withLoadingComponent(<MessageChatPage />),
errorElement: <ErrorPage />,
meta: {
id: 1410,
title: '客服消息',
icon: <CommentOutlined />,
develop: true,
},
},
],
},
];
import dayjs from 'dayjs';
export const base64ToFile = (dataUrl: string, name?: string) => {
const arr: string[] = dataUrl.split(',');
// const mime = arr[0].match(/:(.*?);/)[1];
......@@ -42,3 +44,18 @@ export const filterObjAttr = (obj: any, key: string[]) => {
return pre;
}, {});
};
// 转换时间
export const transDateStr = (date?: string) => {
const days = dayjs().diff(dayjs(date), 'day');
const years = dayjs().year() - dayjs(date).year();
if (years > 1) {
return `${dayjs(date).format('YYYY年MM月DD日')}`;
}
if (days === 1) {
return `昨天`;
}
if (days > 1) {
return `${dayjs(date).format('M月D日')}`;
}
return dayjs(date).format('HH:mm');
};
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论