Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
A
admin
概览
概览
详情
活动
周期分析
版本库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
iuav
admin
Commits
682cdc31
提交
682cdc31
authored
4月 24, 2024
作者:
ZhangLingKun
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
功能:消息管理-客服消息
上级
fea29bda
流水线
#9023
已通过 于阶段
in 1 分 4 秒
变更
13
流水线
1
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
1078 行增加
和
1 行删除
+1078
-1
commonType.ts
src/api/interface/commonType.ts
+94
-0
systemManageType.ts
src/api/interface/systemManageType.ts
+110
-0
systemManage.ts
src/api/modules/systemManage.ts
+25
-0
index.tsx
src/components/qrcodeView/index.tsx
+44
-0
index.tsx
src/components/uploader/index.tsx
+9
-1
index.tsx
...essageManage/messageChat/comp/messageChatAction/index.tsx
+85
-0
index.tsx
...ssageManage/messageChat/comp/messageChatContent/index.tsx
+119
-0
index.tsx
.../messageManage/messageChat/comp/messageChatList/index.tsx
+117
-0
index.tsx
...essageManage/messageChat/comp/messageChatSystem/index.tsx
+65
-0
index.scss
src/pages/messageManage/messageChat/index.scss
+239
-0
index.tsx
src/pages/messageManage/messageChat/index.tsx
+129
-0
router.tsx
src/router/router.tsx
+25
-0
index.ts
src/utils/index.ts
+17
-0
没有找到文件。
src/api/interface/commonType.ts
浏览文件 @
682cdc31
...
...
@@ -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
;
};
};
src/api/interface/systemManageType.ts
浏览文件 @
682cdc31
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
;
}
>
;
src/api/modules/systemManage.ts
浏览文件 @
682cdc31
...
...
@@ -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
);
}
src/components/qrcodeView/index.tsx
0 → 100644
浏览文件 @
682cdc31
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
;
src/components/uploader/index.tsx
浏览文件 @
682cdc31
...
...
@@ -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
&&
(
...
...
src/pages/messageManage/messageChat/comp/messageChatAction/index.tsx
0 → 100644
浏览文件 @
682cdc31
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
;
src/pages/messageManage/messageChat/comp/messageChatContent/index.tsx
0 → 100644
浏览文件 @
682cdc31
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;
src/pages/messageManage/messageChat/comp/messageChatList/index.tsx
0 → 100644
浏览文件 @
682cdc31
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
;
src/pages/messageManage/messageChat/comp/messageChatSystem/index.tsx
0 → 100644
浏览文件 @
682cdc31
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
;
src/pages/messageManage/messageChat/index.scss
0 → 100644
浏览文件 @
682cdc31
.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
;
}
}
}
src/pages/messageManage/messageChat/index.tsx
0 → 100644
浏览文件 @
682cdc31
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;
src/router/router.tsx
浏览文件 @
682cdc31
...
...
@@ -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
,
},
},
],
},
];
src/utils/index.ts
浏览文件 @
682cdc31
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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论