Add chat box

This commit is contained in:
Yang Luo
2023-04-09 22:42:33 +08:00
parent 8b9e0ba96b
commit 754fa1e745
6 changed files with 127 additions and 24 deletions

View File

@ -37,8 +37,17 @@ func (c *ApiController) GetMessages() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
chat := c.Input().Get("chat")
if limit == "" || page == "" { if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedMessages(object.GetMessages(owner)) var messages []*object.Message
if chat == "" {
messages = object.GetMessages(owner)
} else {
messages = object.GetChatMessages(chat)
}
c.Data["json"] = object.GetMaskedMessages(messages)
c.ServeJSON() c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)

View File

@ -27,7 +27,7 @@ type Message struct {
CreatedTime string `xorm:"varchar(100)" json:"createdTime"` CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
Organization string `xorm:"varchar(100)" json:"organization"` Organization string `xorm:"varchar(100)" json:"organization"`
Chat string `xorm:"varchar(100)" json:"chat"` Chat string `xorm:"varchar(100) index" json:"chat"`
Author string `xorm:"varchar(100)" json:"author"` Author string `xorm:"varchar(100)" json:"author"`
Text string `xorm:"mediumtext" json:"text"` Text string `xorm:"mediumtext" json:"text"`
} }
@ -67,6 +67,16 @@ func GetMessages(owner string) []*Message {
return messages return messages
} }
func GetChatMessages(chat string) []*Message {
messages := []*Message{}
err := adapter.Engine.Desc("created_time").Find(&messages, &Message{Chat: chat})
if err != nil {
panic(err)
}
return messages
}
func GetPaginationMessages(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Message { func GetPaginationMessages(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Message {
messages := []*Message{} messages := []*Message{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder) session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)

44
web/src/ChatBox.js Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from "react";
import {Avatar, List} from "antd";
import {CopyOutlined, DislikeOutlined, LikeOutlined} from "@ant-design/icons";
class ChatBox extends React.Component {
render() {
return (
<List
itemLayout="horizontal"
dataSource={this.props.messages}
renderItem={(item, index) => (
<List.Item style={{backgroundColor: index % 2 === 0 ? "white" : "rgb(247,247,248)", borderBottom: "1px solid rgb(229, 229, 229)", position: "relative"}}>
<List.Item.Meta
avatar={<Avatar style={{width: "30px", height: "30px", borderRadius: "3px"}} src={item.author === `${this.props.account.owner}/${this.props.account.name}` ? this.props.account.avatar : "https://cdn.casbin.com/casdoor/resource/built-in/admin/gpt.png"} />}
title={<div style={{fontSize: "16px", fontWeight: "normal", lineHeight: "24px", marginTop: "-15px", marginLeft: "5px", marginRight: "70px"}}>{item.text}</div>}
/>
<div style={{position: "absolute", top: "10px", right: "10px"}}
>
<CopyOutlined style={{color: "rgb(172,172,190)", margin: "5px"}} />
<LikeOutlined style={{color: "rgb(172,172,190)", margin: "5px"}} />
<DislikeOutlined style={{color: "rgb(172,172,190)", margin: "5px"}} />
</div>
</List.Item>
)}
/>
);
}
}
export default ChatBox;

View File

@ -14,13 +14,14 @@
import React from "react"; import React from "react";
import {Menu} from "antd"; import {Menu} from "antd";
import {MailOutlined} from "@ant-design/icons"; import {LayoutOutlined} from "@ant-design/icons";
class ChatMenu extends React.Component { class ChatMenu extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
openKeys: ["0"], openKeys: ["0"],
selectedKeys: ["0-0"],
}; };
} }
@ -36,19 +37,37 @@ class ChatMenu extends React.Component {
return Object.keys(categories).map((category, index) => { return Object.keys(categories).map((category, index) => {
return { return {
key: `${index}`, key: `${index}`,
icon: <MailOutlined />, icon: <LayoutOutlined />,
label: category, label: category,
children: categories[category].map((chat) => ({ children: categories[category].map((chat, chatIndex) => {
key: chat.id, const globalChatIndex = chats.indexOf(chat);
return {
key: `${index}-${chatIndex}`,
dataIndex: globalChatIndex,
label: chat.displayName, label: chat.displayName,
})), };
}),
}; };
}); });
} }
// 处理菜单展开事件 onSelect = (info) => {
const [categoryIndex, chatIndex] = info.selectedKeys[0].split("-").map(Number);
const selectedItem = this.chatsToItems(this.props.chats)[categoryIndex].children[chatIndex];
this.setState({selectedKeys: [`${categoryIndex}-${chatIndex}`]});
if (this.props.onSelect) {
this.props.onSelect(selectedItem.dataIndex);
}
};
getRootSubmenuKeys(items) {
return items.map((item, index) => `${index}`);
}
onOpenChange = (keys) => { onOpenChange = (keys) => {
const rootSubmenuKeys = this.props.chats.map((_, index) => `${index}`); const items = this.chatsToItems(this.props.chats);
const rootSubmenuKeys = this.getRootSubmenuKeys(items);
const latestOpenKey = keys.find((key) => this.state.openKeys.indexOf(key) === -1); const latestOpenKey = keys.find((key) => this.state.openKeys.indexOf(key) === -1);
if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) { if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
@ -65,10 +84,9 @@ class ChatMenu extends React.Component {
<Menu <Menu
mode="inline" mode="inline"
openKeys={this.state.openKeys} openKeys={this.state.openKeys}
selectedKeys={this.state.selectedKeys}
onOpenChange={this.onOpenChange} onOpenChange={this.onOpenChange}
style={{ onSelect={this.onSelect}
width: 256,
}}
items={items} items={items}
/> />
); );

View File

@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import {Col, Row} from "antd";
// import React from "react";
import moment from "moment";
import React from "react"; import React from "react";
import moment from "moment";
import ChatMenu from "./ChatMenu"; import ChatMenu from "./ChatMenu";
import ChatBox from "./ChatBox";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
import * as ChatBackend from "./backend/ChatBackend"; import * as ChatBackend from "./backend/ChatBackend";
import * as MessageBackend from "./backend/MessageBackend";
import i18next from "i18next"; import i18next from "i18next";
import BaseListPage from "./BaseListPage"; import BaseListPage from "./BaseListPage";
@ -77,14 +77,17 @@ class ChatListPage extends BaseListPage {
renderTable(chats) { renderTable(chats) {
return ( return (
<Row style={{marginTop: "10px"}} > <div style={{display: "flex", height: "calc(100vh - 197px)"}}>
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}> <div style={{width: "250px", height: "100%", backgroundColor: "lightblue"}}>
<ChatMenu chats={this.state.data} /> <ChatMenu chats={this.state.data} onSelect={(i) => {
</Col> const chat = chats[i];
<Col span={22} > this.getMessages(chat.name);
222 }} />
</Col> </div>
</Row> <div style={{flex: 1, height: "100%", backgroundColor: "lightgreen"}}>
<ChatBox messages={this.state.messages} account={this.props.account} />
</div>
</div>
); );
} }
@ -122,6 +125,15 @@ class ChatListPage extends BaseListPage {
} }
}); });
}; };
getMessages(chatName) {
MessageBackend.getChatMessages(chatName)
.then((messages) => {
this.setState({
messages: messages,
});
});
}
} }
export default ChatListPage; export default ChatListPage;

View File

@ -24,6 +24,16 @@ export function getMessages(owner, page = "", pageSize = "", field = "", value =
}).then(res => res.json()); }).then(res => res.json());
} }
export function getChatMessages(chat) {
return fetch(`${Setting.ServerUrl}/api/get-messages?chat=${chat}`, {
method: "GET",
credentials: "include",
headers: {
"Accept-Language": Setting.getAcceptLanguage(),
},
}).then(res => res.json());
}
export function getMessage(owner, name) { export function getMessage(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-message?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/get-message?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET", method: "GET",