重构快捷语管理模块:新增快捷回复和分组管理功能,优化数据展示和交互逻辑,提升用户体验和代码可读性。
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import request from "@/api/request";
|
||||
// 快捷回复项接口
|
||||
export interface QuickWordsReply {
|
||||
id: number;
|
||||
groupId: number;
|
||||
userId: number;
|
||||
title: string;
|
||||
msgType: number;
|
||||
content: string;
|
||||
createTime: string;
|
||||
lastUpdateTime: string;
|
||||
sortIndex: string;
|
||||
updateTime: string | null;
|
||||
isDel: number;
|
||||
delTime: string | null;
|
||||
}
|
||||
|
||||
// 快捷回复组接口
|
||||
export interface QuickWordsItem {
|
||||
id: number;
|
||||
groupName: string;
|
||||
sortIndex: string;
|
||||
parentId: number;
|
||||
replyType: string;
|
||||
replys: any | null;
|
||||
companyId: number;
|
||||
userId: number;
|
||||
replies: QuickWordsReply[];
|
||||
children: QuickWordsItem[];
|
||||
}
|
||||
|
||||
//好友接待配置
|
||||
export function setFriendInjectConfig(params: any): Promise<QuickWordsItem[]> {
|
||||
return request("/v1/kefu/reply/list", params, "GET");
|
||||
}
|
||||
|
||||
export interface AddReplyRequest {
|
||||
id?: string;
|
||||
content?: string;
|
||||
groupId?: string;
|
||||
/**
|
||||
* 1文本 3图片 43视频 49链接 等
|
||||
*/
|
||||
msgType?: string[];
|
||||
/**
|
||||
* 默认50
|
||||
*/
|
||||
sortIndex?: string;
|
||||
title?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 添加快捷回复
|
||||
export function addReply(params: AddReplyRequest): Promise<any> {
|
||||
return request("/v1/kefu/reply/addReply", params, "POST");
|
||||
}
|
||||
|
||||
// 更新快捷回复
|
||||
export function updateReply(params: AddReplyRequest): Promise<any> {
|
||||
return request("/v1/kefu/reply/updateReply", params, "POST");
|
||||
}
|
||||
|
||||
// 删除快捷回复
|
||||
export function deleteReply(params: { id: string }): Promise<any> {
|
||||
return request("/v1/kefu/reply/deleteReply", params, "DELETE");
|
||||
}
|
||||
|
||||
export interface AddGroupRequest {
|
||||
id?: string;
|
||||
groupName?: string;
|
||||
parentId?: string;
|
||||
/**
|
||||
* 0 公共 1私有 2部门
|
||||
*/
|
||||
replyType?: string[];
|
||||
/**
|
||||
* 默认50
|
||||
*/
|
||||
sortIndex?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 添加快捷回复组
|
||||
export function addGroup(params: AddGroupRequest): Promise<any> {
|
||||
return request("/v1/kefu/reply/addGroup", params, "POST");
|
||||
}
|
||||
|
||||
// 更新快捷回复组
|
||||
export function updateGroup(params: AddGroupRequest): Promise<any> {
|
||||
return request("/v1/kefu/reply/updateGroup", params, "POST");
|
||||
}
|
||||
|
||||
// 删除快捷回复组
|
||||
export function deleteGroup(params: { id: string }): Promise<any> {
|
||||
return request("/v1/kefu/reply/deleteGroup", params, "DELETE");
|
||||
}
|
||||
@@ -1,135 +1,563 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { Card, Input, Button, Space, List, Tag } from "antd";
|
||||
import React, { useMemo, useState, useEffect, useCallback } from "react";
|
||||
import {
|
||||
Card,
|
||||
Input,
|
||||
Button,
|
||||
Space,
|
||||
Tabs,
|
||||
Tree,
|
||||
Modal,
|
||||
Form,
|
||||
Select,
|
||||
message,
|
||||
Tooltip,
|
||||
Spin,
|
||||
} from "antd";
|
||||
import {
|
||||
PlusOutlined,
|
||||
ReloadOutlined,
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
FileTextOutlined,
|
||||
PictureOutlined,
|
||||
PlayCircleOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import {
|
||||
QuickWordsItem,
|
||||
QuickWordsReply,
|
||||
setFriendInjectConfig,
|
||||
addReply,
|
||||
updateReply,
|
||||
deleteReply,
|
||||
updateGroup,
|
||||
deleteGroup,
|
||||
AddReplyRequest,
|
||||
AddGroupRequest,
|
||||
} from "./api";
|
||||
|
||||
export interface QuickWordItem {
|
||||
id: string | number;
|
||||
text?: string; // 兼容旧结构
|
||||
title?: string;
|
||||
content?: string;
|
||||
tag?: string; // 分类/标签
|
||||
usageCount?: number;
|
||||
// 消息类型枚举
|
||||
export enum MessageType {
|
||||
TEXT = 1,
|
||||
IMAGE = 3,
|
||||
VIDEO = 43,
|
||||
LINK = 49,
|
||||
}
|
||||
|
||||
// 快捷语类型枚举
|
||||
export enum QuickWordsType {
|
||||
PERSONAL = 1, // 个人
|
||||
PUBLIC = 0, // 公共
|
||||
DEPARTMENT = 2, // 部门
|
||||
}
|
||||
|
||||
export interface QuickWordsProps {
|
||||
title?: string;
|
||||
words: QuickWordItem[];
|
||||
onInsert?: (text: string) => void;
|
||||
onAdd?: (text: string) => void;
|
||||
onRemove?: (id: string | number) => void;
|
||||
onInsert?: (reply: QuickWordsReply) => void;
|
||||
}
|
||||
|
||||
const QuickWords: React.FC<QuickWordsProps> = ({
|
||||
title = "快捷语录",
|
||||
words,
|
||||
onInsert,
|
||||
|
||||
onRemove,
|
||||
}) => {
|
||||
const [keyword, setKeyword] = useState("");
|
||||
const sorted = useMemo(
|
||||
() =>
|
||||
[...(words || [])].sort((a, b) =>
|
||||
String(a.id).localeCompare(String(b.id)),
|
||||
),
|
||||
[words],
|
||||
const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
const [activeTab, setActiveTab] = useState<QuickWordsType>(
|
||||
QuickWordsType.PUBLIC,
|
||||
);
|
||||
const [keyword, setKeyword] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [quickWordsData, setQuickWordsData] = useState<QuickWordsItem[]>([]);
|
||||
const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
|
||||
const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
|
||||
|
||||
// 模态框状态
|
||||
const [addModalVisible, setAddModalVisible] = useState(false);
|
||||
const [editModalVisible, setEditModalVisible] = useState(false);
|
||||
const [groupModalVisible, setGroupModalVisible] = useState(false);
|
||||
const [editingItem, setEditingItem] = useState<QuickWordsReply | null>(null);
|
||||
const [editingGroup, setEditingGroup] = useState<QuickWordsItem | null>(null);
|
||||
const [form] = Form.useForm();
|
||||
const [groupForm] = Form.useForm();
|
||||
|
||||
// 获取快捷语数据
|
||||
const fetchQuickWords = useCallback(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await setFriendInjectConfig({ replyType: activeTab });
|
||||
setQuickWordsData(data || []);
|
||||
} catch (error) {
|
||||
message.error("获取快捷语数据失败");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [activeTab]);
|
||||
|
||||
// 初始化数据
|
||||
useEffect(() => {
|
||||
fetchQuickWords();
|
||||
}, [fetchQuickWords]);
|
||||
|
||||
// 获取消息类型图标
|
||||
const getMessageTypeIcon = (msgType: number) => {
|
||||
switch (msgType) {
|
||||
case MessageType.TEXT:
|
||||
return <FileTextOutlined style={{ color: "#1890ff" }} />;
|
||||
case MessageType.IMAGE:
|
||||
return <PictureOutlined style={{ color: "#52c41a" }} />;
|
||||
case MessageType.VIDEO:
|
||||
return <PlayCircleOutlined style={{ color: "#fa8c16" }} />;
|
||||
default:
|
||||
return <FileTextOutlined style={{ color: "#8c8c8c" }} />;
|
||||
}
|
||||
};
|
||||
|
||||
// 将数据转换为Tree组件需要的格式
|
||||
const convertToTreeData = (data: QuickWordsItem[]): any[] => {
|
||||
return data.map(item => ({
|
||||
key: `group-${item.id}`,
|
||||
title: (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<span>{item.groupName}</span>
|
||||
<div style={{ display: "flex", gap: 4 }}>
|
||||
<Tooltip title="编辑分组">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<EditOutlined />}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
handleEditGroup(item);
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title="删除分组">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
handleDeleteGroup(item.id);
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
children: [
|
||||
...item.replies.map(reply => ({
|
||||
key: `reply-${reply.id}`,
|
||||
title: (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||
{getMessageTypeIcon(reply.msgType)}
|
||||
<span>{reply.title}</span>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 4 }}>
|
||||
<Tooltip title="使用">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
onInsert?.(reply);
|
||||
}}
|
||||
>
|
||||
使用
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="编辑">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<EditOutlined />}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
handleEditReply(reply);
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title="删除">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
handleDeleteReply(reply.id);
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
isLeaf: true,
|
||||
})),
|
||||
...convertToTreeData(item.children || []),
|
||||
],
|
||||
}));
|
||||
};
|
||||
|
||||
// 处理添加快捷回复
|
||||
const handleAddReply = async (values: AddReplyRequest) => {
|
||||
try {
|
||||
await addReply({
|
||||
...values,
|
||||
groupId: selectedKeys[0]?.toString().replace("group-", "") || "",
|
||||
replyType: [activeTab.toString()],
|
||||
});
|
||||
message.success("添加快捷回复成功");
|
||||
setAddModalVisible(false);
|
||||
form.resetFields();
|
||||
fetchQuickWords();
|
||||
} catch (error) {
|
||||
message.error("添加快捷回复失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 处理编辑快捷回复
|
||||
const handleEditReply = (reply: QuickWordsReply) => {
|
||||
setEditingItem(reply);
|
||||
form.setFieldsValue({
|
||||
title: reply.title,
|
||||
content: reply.content,
|
||||
msgType: [reply.msgType.toString()],
|
||||
});
|
||||
setEditModalVisible(true);
|
||||
};
|
||||
|
||||
// 处理更新快捷回复
|
||||
const handleUpdateReply = async (values: AddReplyRequest) => {
|
||||
if (!editingItem) return;
|
||||
|
||||
try {
|
||||
await updateReply({
|
||||
...values,
|
||||
id: editingItem.id.toString(),
|
||||
});
|
||||
message.success("更新快捷回复成功");
|
||||
setEditModalVisible(false);
|
||||
setEditingItem(null);
|
||||
form.resetFields();
|
||||
fetchQuickWords();
|
||||
} catch (error) {
|
||||
message.error("更新快捷回复失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 处理删除快捷回复
|
||||
const handleDeleteReply = async (id: number) => {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "确定要删除这个快捷回复吗?",
|
||||
onOk: async () => {
|
||||
try {
|
||||
await deleteReply({ id: id.toString() });
|
||||
message.success("删除成功");
|
||||
fetchQuickWords();
|
||||
} catch (error) {
|
||||
message.error("删除失败");
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 处理编辑分组
|
||||
const handleEditGroup = (group: QuickWordsItem) => {
|
||||
setEditingGroup(group);
|
||||
groupForm.setFieldsValue({
|
||||
groupName: group.groupName,
|
||||
replyType: [group.replyType],
|
||||
});
|
||||
setGroupModalVisible(true);
|
||||
};
|
||||
|
||||
// 处理更新分组
|
||||
const handleUpdateGroup = async (values: AddGroupRequest) => {
|
||||
if (!editingGroup) return;
|
||||
|
||||
try {
|
||||
await updateGroup({
|
||||
...values,
|
||||
id: editingGroup.id.toString(),
|
||||
});
|
||||
message.success("更新分组成功");
|
||||
setGroupModalVisible(false);
|
||||
setEditingGroup(null);
|
||||
groupForm.resetFields();
|
||||
fetchQuickWords();
|
||||
} catch (error) {
|
||||
message.error("更新分组失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 处理删除分组
|
||||
const handleDeleteGroup = async (id: number) => {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "确定要删除这个分组吗?删除后该分组下的所有快捷回复也会被删除。",
|
||||
onOk: async () => {
|
||||
try {
|
||||
await deleteGroup({ id: id.toString() });
|
||||
message.success("删除成功");
|
||||
fetchQuickWords();
|
||||
} catch (error) {
|
||||
message.error("删除失败");
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 过滤数据
|
||||
const filteredData = useMemo(() => {
|
||||
if (!keyword.trim()) return quickWordsData;
|
||||
|
||||
const filterData = (data: QuickWordsItem[]): QuickWordsItem[] => {
|
||||
return data
|
||||
.map(item => ({
|
||||
...item,
|
||||
replies: item.replies.filter(
|
||||
reply =>
|
||||
reply.title.toLowerCase().includes(keyword.toLowerCase()) ||
|
||||
reply.content.toLowerCase().includes(keyword.toLowerCase()),
|
||||
),
|
||||
children: filterData(item.children || []),
|
||||
}))
|
||||
.filter(
|
||||
item =>
|
||||
item.replies.length > 0 ||
|
||||
item.children.length > 0 ||
|
||||
item.groupName.toLowerCase().includes(keyword.toLowerCase()),
|
||||
);
|
||||
};
|
||||
|
||||
return filterData(quickWordsData);
|
||||
}, [quickWordsData, keyword]);
|
||||
|
||||
const treeData = convertToTreeData(filteredData);
|
||||
|
||||
return (
|
||||
<Card title={title} style={{ marginTop: 12 }}>
|
||||
<Space direction="vertical" style={{ width: "100%" }}>
|
||||
<Input.Search
|
||||
placeholder="搜索快捷语录..."
|
||||
allowClear
|
||||
value={keyword}
|
||||
onChange={e => setKeyword(e.target.value)}
|
||||
onSearch={v => setKeyword(v)}
|
||||
/>
|
||||
<Card style={{ marginTop: 12 }}>
|
||||
<Tabs
|
||||
activeKey={activeTab.toString()}
|
||||
onChange={key => setActiveTab(Number(key) as QuickWordsType)}
|
||||
items={[
|
||||
{
|
||||
key: QuickWordsType.PERSONAL.toString(),
|
||||
label: "个人快捷语",
|
||||
},
|
||||
{
|
||||
key: QuickWordsType.PUBLIC.toString(),
|
||||
label: "公共快捷语",
|
||||
},
|
||||
{
|
||||
key: QuickWordsType.DEPARTMENT.toString(),
|
||||
label: "部门快捷语",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<List
|
||||
itemLayout="vertical"
|
||||
split={false}
|
||||
dataSource={sorted.filter(item => {
|
||||
const text = `${item.title || ""}${item.content || ""}${item.text || ""}`;
|
||||
return text.toLowerCase().includes(keyword.trim().toLowerCase());
|
||||
})}
|
||||
renderItem={item => {
|
||||
const displayTitle = item.title || item.text || "未命名";
|
||||
const displayContent = item.content || item.text || "";
|
||||
return (
|
||||
<List.Item
|
||||
style={{
|
||||
padding: "12px 8px",
|
||||
border: "1px solid #f0f0f0",
|
||||
borderRadius: 8,
|
||||
marginBottom: 12,
|
||||
background: "#fff",
|
||||
<Space direction="vertical" style={{ width: "100%", marginTop: 16 }}>
|
||||
<div style={{ display: "flex", gap: 8, alignItems: "center" }}>
|
||||
<Input.Search
|
||||
placeholder="输入关键字过滤"
|
||||
allowClear
|
||||
value={keyword}
|
||||
onChange={e => setKeyword(e.target.value)}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
<Tooltip title="添加快捷回复">
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => setAddModalVisible(true)}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title="刷新">
|
||||
<Button icon={<ReloadOutlined />} onClick={fetchQuickWords} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<Spin spinning={loading}>
|
||||
<Tree
|
||||
showLine
|
||||
showIcon
|
||||
expandedKeys={expandedKeys}
|
||||
selectedKeys={selectedKeys}
|
||||
onExpand={setExpandedKeys}
|
||||
onSelect={setSelectedKeys}
|
||||
treeData={treeData}
|
||||
style={{ maxHeight: 400, overflow: "auto" }}
|
||||
/>
|
||||
</Spin>
|
||||
</Space>
|
||||
|
||||
{/* 添加快捷回复模态框 */}
|
||||
<Modal
|
||||
title="添加快捷回复"
|
||||
open={addModalVisible}
|
||||
onCancel={() => {
|
||||
setAddModalVisible(false);
|
||||
form.resetFields();
|
||||
}}
|
||||
footer={null}
|
||||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleAddReply}>
|
||||
<Form.Item
|
||||
name="title"
|
||||
label="标题"
|
||||
rules={[{ required: true, message: "请输入标题" }]}
|
||||
>
|
||||
<Input placeholder="请输入快捷回复标题" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="content"
|
||||
label="内容"
|
||||
rules={[{ required: true, message: "请输入内容" }]}
|
||||
>
|
||||
<Input.TextArea rows={4} placeholder="请输入快捷回复内容" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="msgType"
|
||||
label="消息类型"
|
||||
rules={[{ required: true, message: "请选择消息类型" }]}
|
||||
>
|
||||
<Select placeholder="请选择消息类型">
|
||||
<Select.Option value="1">文本</Select.Option>
|
||||
<Select.Option value="3">图片</Select.Option>
|
||||
<Select.Option value="43">视频</Select.Option>
|
||||
<Select.Option value="49">链接</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
确定
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setAddModalVisible(false);
|
||||
form.resetFields();
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
marginBottom: 6,
|
||||
}}
|
||||
>
|
||||
{item.tag && <Tag color="blue">{item.tag}</Tag>}
|
||||
<span style={{ fontWeight: 600, color: "#262626" }}>
|
||||
{displayTitle}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#8c8c8c",
|
||||
fontSize: 13,
|
||||
lineHeight: 1.6,
|
||||
whiteSpace: "pre-wrap",
|
||||
}}
|
||||
>
|
||||
{displayContent}
|
||||
</div>
|
||||
{typeof item.usageCount === "number" && (
|
||||
<div
|
||||
style={{ color: "#bfbfbf", fontSize: 12, marginTop: 6 }}
|
||||
>
|
||||
使用 {item.usageCount} 次
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
style={{ display: "flex", alignItems: "center", gap: 8 }}
|
||||
>
|
||||
{onRemove && (
|
||||
<Button
|
||||
size="small"
|
||||
danger
|
||||
onClick={() => onRemove(item.id)}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={() => onInsert?.(displayContent || displayTitle)}
|
||||
>
|
||||
使用
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</List.Item>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
{/* 编辑快捷回复模态框 */}
|
||||
<Modal
|
||||
title="编辑快捷回复"
|
||||
open={editModalVisible}
|
||||
onCancel={() => {
|
||||
setEditModalVisible(false);
|
||||
setEditingItem(null);
|
||||
form.resetFields();
|
||||
}}
|
||||
footer={null}
|
||||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleUpdateReply}>
|
||||
<Form.Item
|
||||
name="title"
|
||||
label="标题"
|
||||
rules={[{ required: true, message: "请输入标题" }]}
|
||||
>
|
||||
<Input placeholder="请输入快捷回复标题" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="content"
|
||||
label="内容"
|
||||
rules={[{ required: true, message: "请输入内容" }]}
|
||||
>
|
||||
<Input.TextArea rows={4} placeholder="请输入快捷回复内容" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="msgType"
|
||||
label="消息类型"
|
||||
rules={[{ required: true, message: "请选择消息类型" }]}
|
||||
>
|
||||
<Select placeholder="请选择消息类型">
|
||||
<Select.Option value="1">文本</Select.Option>
|
||||
<Select.Option value="3">图片</Select.Option>
|
||||
<Select.Option value="43">视频</Select.Option>
|
||||
<Select.Option value="49">链接</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
确定
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setEditModalVisible(false);
|
||||
setEditingItem(null);
|
||||
form.resetFields();
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
{/* 编辑分组模态框 */}
|
||||
<Modal
|
||||
title="编辑分组"
|
||||
open={groupModalVisible}
|
||||
onCancel={() => {
|
||||
setGroupModalVisible(false);
|
||||
setEditingGroup(null);
|
||||
groupForm.resetFields();
|
||||
}}
|
||||
footer={null}
|
||||
>
|
||||
<Form form={groupForm} layout="vertical" onFinish={handleUpdateGroup}>
|
||||
<Form.Item
|
||||
name="groupName"
|
||||
label="分组名称"
|
||||
rules={[{ required: true, message: "请输入分组名称" }]}
|
||||
>
|
||||
<Input placeholder="请输入分组名称" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
确定
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setGroupModalVisible(false);
|
||||
setEditingGroup(null);
|
||||
groupForm.resetFields();
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user