Refactor GlobalPromptModal to use antd-mobile Popup for improved mobile experience. Update styles for modal footer and enhance user feedback with Toast notifications. Remove deprecated Ant Design Modal components and adjust layout for better usability.

This commit is contained in:
超级老白兔
2025-10-30 16:26:15 +08:00
parent 515c85e600
commit da87f9a865
2 changed files with 79 additions and 53 deletions

View File

@@ -1,12 +1,14 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Modal, Switch, message } from "antd"; import { Popup, Toast } from "antd-mobile";
import { Input, Button, Switch } from "antd";
import { CloseOutlined } from "@ant-design/icons";
const { TextArea } = Input;
import { import {
InfoCircleOutlined, InfoCircleOutlined,
BulbOutlined, ExclamationCircleFilled,
ExclamationCircleOutlined, InfoCircleFilled,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { getGlobalPrompt, saveGlobalPrompt } from "../api"; import { getGlobalPrompt, saveGlobalPrompt } from "../api";
import type { GlobalPromptConfig } from "../data";
import style from "../index.module.scss"; import style from "../index.module.scss";
interface GlobalPromptModalProps { interface GlobalPromptModalProps {
@@ -35,6 +37,7 @@ const GlobalPromptModal: React.FC<GlobalPromptModalProps> = ({
if (visible) { if (visible) {
fetchGlobalPrompt(); fetchGlobalPrompt();
} }
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible]); }, [visible]);
const fetchGlobalPrompt = async () => { const fetchGlobalPrompt = async () => {
@@ -44,7 +47,7 @@ const GlobalPromptModal: React.FC<GlobalPromptModalProps> = ({
setEnabled(config.enabled); setEnabled(config.enabled);
setContent(config.content || DEFAULT_PROMPT); setContent(config.content || DEFAULT_PROMPT);
} catch (error) { } catch (error) {
message.error("获取配置失败"); Toast.show({ content: "获取配置失败", position: "bottom" });
} finally { } finally {
setLoading(false); setLoading(false);
} }
@@ -52,66 +55,83 @@ const GlobalPromptModal: React.FC<GlobalPromptModalProps> = ({
const handleSave = async () => { const handleSave = async () => {
if (enabled && !content.trim()) { if (enabled && !content.trim()) {
message.error("启用统一提示词时,请输入提示词内容"); Toast.show({
content: "启用统一提示词时,请输入提示词内容",
position: "bottom",
});
return; return;
} }
setSaving(true); setSaving(true);
try { try {
await saveGlobalPrompt({ await saveGlobalPrompt({
enabled, enabled,
content: content.trim(), content: content.trim(),
}); });
message.success("保存成功"); Toast.show({ content: "保存成功", position: "bottom" });
onClose(); onClose();
} catch (error) { } catch (error) {
message.error("保存失败"); Toast.show({ content: "保存失败", position: "bottom" });
} finally { } finally {
setSaving(false); setSaving(false);
} }
}; };
return ( return (
<Modal <Popup
title={ visible={visible}
<div style={{ display: "flex", alignItems: "center", gap: 8 }}> onMaskClick={onClose}
<InfoCircleOutlined style={{ color: "#1890ff" }} /> bodyStyle={{ borderRadius: "16px 16px 0 0", minHeight: 300, padding: 0 }}
position="bottom"
</div> closeOnMaskClick
}
open={visible}
onCancel={onClose}
onOk={handleSave}
confirmLoading={saving}
width={600}
okText="保存配置"
cancelText="取消"
className={style.promptModal} className={style.promptModal}
> >
<div
className={style.promptMobileHead}
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: "18px 20px 0 20px",
}}
>
<div style={{ display: "flex", alignItems: "center" }}>
<InfoCircleOutlined
style={{
color: "#1677ff",
fontSize: 20,
marginRight: 8,
verticalAlign: "middle",
}}
/>
<span></span>
</div>
<CloseOutlined onClick={onClose} />
</div>
<div className={style.promptContent}> <div className={style.promptContent}>
<p style={{ fontSize: 13, color: "#666", marginBottom: 16 }}> <div style={{ fontSize: 13, color: "#888", marginBottom: 12 }}>
</p> </div>
<div className={style.promptToggle}> <div className={style.promptToggle}>
<span className={style.promptToggleLabel}></span> <span className={style.promptToggleLabel}></span>
<Switch checked={enabled} onChange={setEnabled} /> <Switch checked={enabled} onChange={setEnabled} loading={loading} />
</div> </div>
{enabled && ( {enabled && (
<textarea <TextArea
className={style.promptTextarea}
value={content} value={content}
onChange={e => setContent(e.target.value)} onChange={e => setContent(e.target.value)}
placeholder="请输入统一提示词..." placeholder="请输入统一提示词..."
maxLength={2000} maxLength={2000}
disabled={loading}
className={style.promptTextarea}
/> />
)} )}
<div className={style.promptSection}> <div className={style.promptSection}>
<div className={style.sectionTitle}> <div className={style.sectionTitle}>
<BulbOutlined className={style.sectionIcon} /> <InfoCircleFilled
: className={style.sectionIcon}
style={{ fontSize: 16 }}
/>
</div> </div>
<div className={style.sectionContent}> <div className={style.sectionContent}>
<ul> <ul>
@@ -121,18 +141,38 @@ const GlobalPromptModal: React.FC<GlobalPromptModalProps> = ({
</ul> </ul>
</div> </div>
</div> </div>
<div className={style.warningBox}> <div className={style.warningBox}>
<div className={style.warningTitle}> <div className={style.warningTitle}>
<ExclamationCircleOutlined /> : <ExclamationCircleFilled
style={{
marginRight: 3,
fontSize: 16,
verticalAlign: "middle",
color: "#FC772B",
}}
/>
:
</div> </div>
<div className={style.warningText}> <div className={style.warningText}>
<div> + </div> + =
<div style={{ marginTop: 4 }}>= AI回复内容</div> AI回复内容
</div> </div>
</div> </div>
<div className={style.modalFooter}>
<Button size="large" onClick={onClose}>
</Button>
<Button
size="large"
onClick={handleSave}
disabled={saving}
type="primary"
>
{saving ? "保存中..." : "保存配置"}
</Button>
</div>
</div> </div>
</Modal> </Popup>
); );
}; };

View File

@@ -296,21 +296,8 @@
.modalFooter { .modalFooter {
display: flex; display: flex;
justify-content: space-between;
gap: 12px; gap: 12px;
padding: 16px 20px;
border-top: 1px solid #f0f0f0;
background: #fff;
}
.modalButton {
flex: 1;
padding: 10px;
border: none;
border-radius: 8px;
font-size: 15px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
} }
.cancelButton { .cancelButton {
@@ -346,7 +333,6 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 12px;
background: #f9f9f9; background: #f9f9f9;
border-radius: 8px; border-radius: 8px;
margin-bottom: 16px; margin-bottom: 16px;