重构快捷语组件:引入Layout组件,优化界面结构和样式,提升用户体验和代码可读性。
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import React from "react";
|
||||
import { Modal, Form, Input, Space, Button } from "antd";
|
||||
import { AddGroupRequest } from "../api";
|
||||
|
||||
export interface GroupModalProps {
|
||||
open: boolean;
|
||||
mode: "add" | "edit";
|
||||
initialValues?: Partial<AddGroupRequest>;
|
||||
onSubmit: (values: AddGroupRequest) => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const GroupModal: React.FC<GroupModalProps> = ({
|
||||
open,
|
||||
mode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
}) => {
|
||||
const [form] = Form.useForm<AddGroupRequest>();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={mode === "add" ? "新增分组" : "编辑分组"}
|
||||
open={open}
|
||||
onCancel={() => {
|
||||
onCancel();
|
||||
form.resetFields();
|
||||
}}
|
||||
footer={null}
|
||||
destroyOnClose
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={values => onSubmit(values)}
|
||||
initialValues={initialValues}
|
||||
>
|
||||
<Form.Item
|
||||
name="groupName"
|
||||
label="分组名称"
|
||||
rules={[{ required: true, message: "请输入分组名称" }]}
|
||||
>
|
||||
<Input placeholder="请输入分组名称" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
确定
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onCancel();
|
||||
form.resetFields();
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default GroupModal;
|
||||
@@ -0,0 +1,247 @@
|
||||
import React, { useMemo } from "react";
|
||||
import { Modal, Form, Input, Select, Space, Button } from "antd";
|
||||
import {
|
||||
PictureOutlined,
|
||||
VideoCameraOutlined,
|
||||
LinkOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import SimpleFileUpload from "@/components/Upload/SimpleFileUpload";
|
||||
// 简化版不再使用样式与解析组件
|
||||
import { AddReplyRequest } from "../api";
|
||||
|
||||
export interface QuickReplyModalProps {
|
||||
open: boolean;
|
||||
mode: "add" | "edit";
|
||||
initialValues?: Partial<AddReplyRequest>;
|
||||
onSubmit: (values: AddReplyRequest) => void;
|
||||
onCancel: () => void;
|
||||
groupOptions?: { label: string; value: string }[];
|
||||
defaultGroupId?: string;
|
||||
}
|
||||
|
||||
const QuickReplyModal: React.FC<QuickReplyModalProps> = ({
|
||||
open,
|
||||
mode,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
groupOptions,
|
||||
defaultGroupId,
|
||||
}) => {
|
||||
const [form] = Form.useForm<AddReplyRequest>();
|
||||
|
||||
const mergedInitialValues = useMemo(() => {
|
||||
return {
|
||||
groupId: defaultGroupId,
|
||||
msgType: initialValues?.msgType || ["1"],
|
||||
...initialValues,
|
||||
} as Partial<AddReplyRequest>;
|
||||
}, [initialValues, defaultGroupId]);
|
||||
|
||||
// 监听类型变化
|
||||
const msgTypeWatch = Form.useWatch("msgType", form);
|
||||
const selectedMsgType = useMemo(() => {
|
||||
const value = msgTypeWatch;
|
||||
const raw = Array.isArray(value) ? value[0] : value;
|
||||
return Number(raw || "1");
|
||||
}, [msgTypeWatch]);
|
||||
|
||||
// 根据文件格式判断消息类型
|
||||
const getMsgTypeByFileFormat = (filePath: string): number => {
|
||||
const extension = filePath.toLowerCase().split(".").pop() || "";
|
||||
const imageFormats = [
|
||||
"jpg",
|
||||
"jpeg",
|
||||
"png",
|
||||
"gif",
|
||||
"bmp",
|
||||
"webp",
|
||||
"svg",
|
||||
"ico",
|
||||
];
|
||||
if (imageFormats.includes(extension)) return 3;
|
||||
const videoFormats = [
|
||||
"mp4",
|
||||
"avi",
|
||||
"mov",
|
||||
"wmv",
|
||||
"flv",
|
||||
"mkv",
|
||||
"webm",
|
||||
"3gp",
|
||||
"rmvb",
|
||||
];
|
||||
if (videoFormats.includes(extension)) return 43;
|
||||
return 49;
|
||||
};
|
||||
|
||||
const FileType = {
|
||||
TEXT: 1,
|
||||
IMAGE: 2,
|
||||
VIDEO: 3,
|
||||
AUDIO: 4,
|
||||
FILE: 5,
|
||||
} as const;
|
||||
|
||||
const handleFileUploaded = (
|
||||
filePath: string | { url: string; durationMs: number },
|
||||
fileType: number,
|
||||
) => {
|
||||
let msgType = 1;
|
||||
if (([FileType.TEXT] as number[]).includes(fileType)) {
|
||||
msgType = getMsgTypeByFileFormat(filePath as string);
|
||||
} else if (([FileType.IMAGE] as number[]).includes(fileType)) {
|
||||
msgType = 3;
|
||||
} else if (([FileType.VIDEO] as number[]).includes(fileType)) {
|
||||
msgType = 43;
|
||||
} else if (([FileType.AUDIO] as number[]).includes(fileType)) {
|
||||
msgType = 34;
|
||||
} else if (([FileType.FILE] as number[]).includes(fileType)) {
|
||||
msgType = 49;
|
||||
}
|
||||
|
||||
form.setFieldsValue({
|
||||
msgType: [String(msgType)],
|
||||
content: ([FileType.AUDIO] as number[]).includes(fileType)
|
||||
? JSON.stringify(filePath)
|
||||
: (filePath as string),
|
||||
});
|
||||
};
|
||||
|
||||
const handleKeyPress = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === "Enter" && !e.ctrlKey && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
form.submit();
|
||||
}
|
||||
};
|
||||
|
||||
// 简化后不再有预览解析
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={mode === "add" ? "添加快捷回复" : "编辑快捷回复"}
|
||||
open={open}
|
||||
onCancel={() => {
|
||||
onCancel();
|
||||
form.resetFields();
|
||||
}}
|
||||
footer={null}
|
||||
destroyOnClose
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={values => {
|
||||
const normalized = {
|
||||
...values,
|
||||
msgType: Array.isArray(values.msgType)
|
||||
? values.msgType
|
||||
: [String(values.msgType)],
|
||||
} as AddReplyRequest;
|
||||
onSubmit(normalized);
|
||||
}}
|
||||
initialValues={mergedInitialValues}
|
||||
>
|
||||
<Space style={{ width: "100%" }} size={24}>
|
||||
<Form.Item
|
||||
name="title"
|
||||
label="标题"
|
||||
rules={[{ required: true, message: "请输入标题" }]}
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
<Input placeholder="请输入快捷语标题" allowClear />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="groupId"
|
||||
label="选择分组"
|
||||
style={{ width: 260 }}
|
||||
rules={[{ required: true, message: "请选择分组" }]}
|
||||
>
|
||||
<Select
|
||||
placeholder="请选择分组"
|
||||
options={groupOptions}
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Space>
|
||||
|
||||
<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
|
||||
name="content"
|
||||
label="内容"
|
||||
rules={[{ required: true, message: "请输入/上传内容" }]}
|
||||
>
|
||||
{selectedMsgType === 1 && (
|
||||
<Input.TextArea
|
||||
rows={4}
|
||||
placeholder="请输入文本内容"
|
||||
value={form.getFieldValue("content")}
|
||||
onChange={e => form.setFieldsValue({ content: e.target.value })}
|
||||
onKeyDown={handleKeyPress}
|
||||
/>
|
||||
)}
|
||||
{selectedMsgType === 3 && (
|
||||
<SimpleFileUpload
|
||||
onFileUploaded={filePath =>
|
||||
handleFileUploaded(filePath, FileType.IMAGE)
|
||||
}
|
||||
maxSize={1}
|
||||
type={1}
|
||||
slot={<Button icon={<PictureOutlined />}>上传图片</Button>}
|
||||
/>
|
||||
)}
|
||||
{selectedMsgType === 43 && (
|
||||
<SimpleFileUpload
|
||||
onFileUploaded={filePath =>
|
||||
handleFileUploaded(filePath, FileType.VIDEO)
|
||||
}
|
||||
maxSize={1}
|
||||
type={4}
|
||||
slot={<Button icon={<VideoCameraOutlined />}>上传视频</Button>}
|
||||
/>
|
||||
)}
|
||||
{selectedMsgType === 49 && (
|
||||
<Input
|
||||
placeholder="请输入链接地址"
|
||||
prefix={<LinkOutlined />}
|
||||
value={form.getFieldValue("content")}
|
||||
onChange={e => form.setFieldsValue({ content: e.target.value })}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
确定
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onCancel();
|
||||
form.resetFields();
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default QuickReplyModal;
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useMemo, useState, useEffect, useCallback } from "react";
|
||||
import {
|
||||
Card,
|
||||
Input,
|
||||
Button,
|
||||
Space,
|
||||
@@ -8,10 +7,10 @@ import {
|
||||
Tree,
|
||||
Modal,
|
||||
Form,
|
||||
Select,
|
||||
message,
|
||||
Tooltip,
|
||||
Spin,
|
||||
Dropdown,
|
||||
} from "antd";
|
||||
import {
|
||||
PlusOutlined,
|
||||
@@ -33,7 +32,12 @@ import {
|
||||
deleteGroup,
|
||||
AddReplyRequest,
|
||||
AddGroupRequest,
|
||||
addGroup,
|
||||
} from "./api";
|
||||
import Layout from "@/components/Layout/LayoutFiexd";
|
||||
import QuickReplyModal from "./components/QuickReplyModal";
|
||||
import GroupModal from "./components/GroupModal";
|
||||
import { useWeChatStore } from "@/store/module/weChat/weChat";
|
||||
|
||||
// 消息类型枚举
|
||||
export enum MessageType {
|
||||
@@ -70,8 +74,12 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
const [groupModalVisible, setGroupModalVisible] = useState(false);
|
||||
const [editingItem, setEditingItem] = useState<QuickWordsReply | null>(null);
|
||||
const [editingGroup, setEditingGroup] = useState<QuickWordsItem | null>(null);
|
||||
const [isAddingGroup, setIsAddingGroup] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
const [groupForm] = Form.useForm();
|
||||
const updateQuoteMessageContent = useWeChatStore(
|
||||
state => state.updateQuoteMessageContent,
|
||||
);
|
||||
|
||||
// 获取快捷语数据
|
||||
const fetchQuickWords = useCallback(async () => {
|
||||
@@ -157,24 +165,26 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
}}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
// 将快捷语内容写入输入框(仅文本或可直接粘贴的内容)
|
||||
try {
|
||||
if ([MessageType.TEXT].includes(reply.msgType)) {
|
||||
updateQuoteMessageContent(reply.content || "");
|
||||
} else if ([MessageType.LINK].includes(reply.msgType)) {
|
||||
updateQuoteMessageContent(reply.content || "");
|
||||
} else {
|
||||
// 非文本类型,插入标题作为占位,方便用户手动调整
|
||||
updateQuoteMessageContent(reply.title || "");
|
||||
}
|
||||
} catch (_) {}
|
||||
}}
|
||||
>
|
||||
<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"
|
||||
@@ -211,9 +221,13 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
// 处理添加快捷回复
|
||||
const handleAddReply = async (values: AddReplyRequest) => {
|
||||
try {
|
||||
const fallbackGroupId =
|
||||
selectedKeys[0]?.toString().replace("group-", "") ||
|
||||
groupOptions[0]?.value ||
|
||||
"";
|
||||
await addReply({
|
||||
...values,
|
||||
groupId: selectedKeys[0]?.toString().replace("group-", "") || "",
|
||||
groupId: values.groupId || fallbackGroupId,
|
||||
replyType: [activeTab.toString()],
|
||||
});
|
||||
message.success("添加快捷回复成功");
|
||||
@@ -228,11 +242,6 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
// 处理编辑快捷回复
|
||||
const handleEditReply = (reply: QuickWordsReply) => {
|
||||
setEditingItem(reply);
|
||||
form.setFieldsValue({
|
||||
title: reply.title,
|
||||
content: reply.content,
|
||||
msgType: [reply.msgType.toString()],
|
||||
});
|
||||
setEditModalVisible(true);
|
||||
};
|
||||
|
||||
@@ -248,7 +257,6 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
message.success("更新快捷回复成功");
|
||||
setEditModalVisible(false);
|
||||
setEditingItem(null);
|
||||
form.resetFields();
|
||||
fetchQuickWords();
|
||||
} catch (error) {
|
||||
message.error("更新快捷回复失败");
|
||||
@@ -274,11 +282,16 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
|
||||
// 处理编辑分组
|
||||
const handleEditGroup = (group: QuickWordsItem) => {
|
||||
setIsAddingGroup(false);
|
||||
setEditingGroup(group);
|
||||
groupForm.setFieldsValue({
|
||||
groupName: group.groupName,
|
||||
replyType: [group.replyType],
|
||||
});
|
||||
setGroupModalVisible(true);
|
||||
};
|
||||
|
||||
// 打开新增分组
|
||||
const handleOpenAddGroup = () => {
|
||||
setIsAddingGroup(true);
|
||||
setEditingGroup(null);
|
||||
groupForm.resetFields();
|
||||
setGroupModalVisible(true);
|
||||
};
|
||||
|
||||
@@ -294,13 +307,31 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
message.success("更新分组成功");
|
||||
setGroupModalVisible(false);
|
||||
setEditingGroup(null);
|
||||
groupForm.resetFields();
|
||||
fetchQuickWords();
|
||||
} catch (error) {
|
||||
message.error("更新分组失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 处理新增分组
|
||||
const handleAddGroup = async (values: AddGroupRequest) => {
|
||||
try {
|
||||
await addGroup({
|
||||
...values,
|
||||
parentId: selectedKeys[0]?.toString().startsWith("group-")
|
||||
? selectedKeys[0]?.toString().replace("group-", "")
|
||||
: "0",
|
||||
replyType: [activeTab.toString()],
|
||||
});
|
||||
message.success("新增分组成功");
|
||||
setGroupModalVisible(false);
|
||||
setIsAddingGroup(false);
|
||||
fetchQuickWords();
|
||||
} catch (error) {
|
||||
message.error("新增分组失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 处理删除分组
|
||||
const handleDeleteGroup = async (id: number) => {
|
||||
Modal.confirm({
|
||||
@@ -346,48 +377,78 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
|
||||
const treeData = convertToTreeData(filteredData);
|
||||
|
||||
// 供新增/编辑快捷语使用的分组下拉数据
|
||||
const groupOptions = useMemo(() => {
|
||||
const flat: { label: string; value: string }[] = [];
|
||||
const walk = (items: QuickWordsItem[]) => {
|
||||
items.forEach(it => {
|
||||
flat.push({ label: it.groupName, value: it.id.toString() });
|
||||
if (it.children && it.children.length) walk(it.children);
|
||||
});
|
||||
};
|
||||
walk(quickWordsData);
|
||||
return flat;
|
||||
}, [quickWordsData]);
|
||||
|
||||
return (
|
||||
<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: "部门快捷语",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<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 }}
|
||||
<Layout
|
||||
header={
|
||||
<div style={{ padding: "0 16px" }}>
|
||||
<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: "部门快捷语",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Tooltip title="添加快捷回复">
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => setAddModalVisible(true)}
|
||||
<div style={{ display: "flex", gap: 8, alignItems: "center" }}>
|
||||
<Input.Search
|
||||
placeholder="输入关键字过滤"
|
||||
allowClear
|
||||
value={keyword}
|
||||
onChange={e => setKeyword(e.target.value)}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title="刷新">
|
||||
<Button icon={<ReloadOutlined />} onClick={fetchQuickWords} />
|
||||
</Tooltip>
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{ key: "add-group", label: "添加新分组" },
|
||||
{ key: "add-reply", label: "新增快捷语" },
|
||||
{ key: "import-reply", label: "导入快捷语" },
|
||||
],
|
||||
onClick: ({ key }) => {
|
||||
if (key === "add-group") return handleOpenAddGroup();
|
||||
if (key === "add-reply") return setAddModalVisible(true);
|
||||
if (key === "import-reply")
|
||||
return message.info("导入快捷语功能开发中");
|
||||
},
|
||||
}}
|
||||
placement="bottomRight"
|
||||
trigger={["click"]}
|
||||
>
|
||||
<Tooltip title="添加">
|
||||
<Button type="primary" icon={<PlusOutlined />} />
|
||||
</Tooltip>
|
||||
</Dropdown>
|
||||
<Tooltip title="刷新">
|
||||
<Button icon={<ReloadOutlined />} onClick={fetchQuickWords} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
>
|
||||
<Space direction="vertical" style={{ width: "100%", padding: 16 }}>
|
||||
<Spin spinning={loading}>
|
||||
<Tree
|
||||
showLine
|
||||
@@ -397,168 +458,60 @@ const QuickWords: React.FC<QuickWordsProps> = ({ onInsert }) => {
|
||||
onExpand={setExpandedKeys}
|
||||
onSelect={setSelectedKeys}
|
||||
treeData={treeData}
|
||||
style={{ maxHeight: 400, overflow: "auto" }}
|
||||
/>
|
||||
</Spin>
|
||||
</Space>
|
||||
|
||||
{/* 添加快捷回复模态框 */}
|
||||
<Modal
|
||||
title="添加快捷回复"
|
||||
<QuickReplyModal
|
||||
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>
|
||||
mode="add"
|
||||
groupOptions={groupOptions}
|
||||
defaultGroupId={
|
||||
selectedKeys[0]?.toString().replace("group-", "") ||
|
||||
groupOptions[0]?.value
|
||||
}
|
||||
onSubmit={handleAddReply}
|
||||
onCancel={() => setAddModalVisible(false)}
|
||||
/>
|
||||
|
||||
<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();
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
{/* 编辑快捷回复模态框 */}
|
||||
<Modal
|
||||
title="编辑快捷回复"
|
||||
<QuickReplyModal
|
||||
open={editModalVisible}
|
||||
mode="edit"
|
||||
groupOptions={groupOptions}
|
||||
defaultGroupId={selectedKeys[0]?.toString().replace("group-", "")}
|
||||
initialValues={
|
||||
editingItem
|
||||
? {
|
||||
title: editingItem.title,
|
||||
content: editingItem.content,
|
||||
msgType: [editingItem.msgType.toString()],
|
||||
groupId:
|
||||
editingItem.groupId?.toString?.() ||
|
||||
selectedKeys[0]?.toString().replace("group-", ""),
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onSubmit={handleUpdateReply}
|
||||
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="编辑分组"
|
||||
<GroupModal
|
||||
open={groupModalVisible}
|
||||
mode={isAddingGroup ? "add" : "edit"}
|
||||
initialValues={
|
||||
editingGroup ? { groupName: editingGroup.groupName } : undefined
|
||||
}
|
||||
onSubmit={isAddingGroup ? handleAddGroup : handleUpdateGroup}
|
||||
onCancel={() => {
|
||||
setGroupModalVisible(false);
|
||||
setEditingGroup(null);
|
||||
groupForm.resetFields();
|
||||
setIsAddingGroup(false);
|
||||
}}
|
||||
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>
|
||||
/>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user