feat: polish reporting templates and shared controls
This commit is contained in:
@@ -3,6 +3,7 @@ import { Edit3, MessageSquare, Plus, Search, Trash2 } from 'lucide-react';
|
||||
import { Button, Input, Modal, Pagination, Select, Tag, Textarea } from '@/components/ui';
|
||||
import { clientApi, type ClientSmsApplication, type ClientSmsSignature, type ClientSmsTemplate } from '@/api/adminApi';
|
||||
import { formatDateTime } from '@/utils/dateTime';
|
||||
import { replaceLeadingSmsSignature } from '@/utils/smsSignature';
|
||||
|
||||
type TemplateVariable = {
|
||||
name: string;
|
||||
@@ -73,12 +74,16 @@ function TemplateModal({
|
||||
const [customVariable, setCustomVariable] = useState('');
|
||||
const [variablesOpen, setVariablesOpen] = useState(false);
|
||||
const contentRef = useRef<HTMLTextAreaElement>(null);
|
||||
const initialSignature = signatures.find((signature) => signature.id === item?.signatureId);
|
||||
const initialContent = item?.signatureId
|
||||
? replaceLeadingSmsSignature(item.content, initialSignature?.name)
|
||||
: item?.content ?? '';
|
||||
const [form, setForm] = useState<TemplateFormState>({
|
||||
applicationId: item?.applicationId ?? '',
|
||||
signatureId: item?.signatureId ?? '',
|
||||
name: item?.name ?? '',
|
||||
category: item?.category ?? '行业通知',
|
||||
content: item?.content ?? '',
|
||||
content: initialContent,
|
||||
variables: item?.variables?.map((variable) => ({ name: variable.name, example: variable.example ?? undefined, required: variable.required ?? true })) ?? [],
|
||||
});
|
||||
const application = applications.find((candidate) => candidate.id === form.applicationId);
|
||||
@@ -97,6 +102,14 @@ function TemplateModal({
|
||||
setForm((current) => ({ ...current, content, variables: extractVariables(content) }));
|
||||
}
|
||||
|
||||
function selectSignature(signatureId: string) {
|
||||
const signature = availableSignatures.find((candidate) => candidate.id === signatureId);
|
||||
setForm((current) => {
|
||||
const content = replaceLeadingSmsSignature(current.content, signature?.name);
|
||||
return { ...current, signatureId, content, variables: extractVariables(content) };
|
||||
});
|
||||
}
|
||||
|
||||
function insertVariable(name: string) {
|
||||
const normalized = name.trim();
|
||||
if (!normalized) return;
|
||||
@@ -120,7 +133,7 @@ function TemplateModal({
|
||||
footer={(
|
||||
<>
|
||||
<Button onClick={onClose} variant="ghost">取消</Button>
|
||||
<Button disabled={!form.applicationId || !form.name || !form.content.trim()} onClick={() => onSubmit({ ...form, variables })}>提交审核</Button>
|
||||
<Button disabled={!form.applicationId || !form.signatureId || !form.name || !form.content.trim()} onClick={() => onSubmit({ ...form, variables })}>提交审核</Button>
|
||||
</>
|
||||
)}
|
||||
onClose={onClose}
|
||||
@@ -137,13 +150,23 @@ function TemplateModal({
|
||||
/>
|
||||
<Select
|
||||
label="短信签名"
|
||||
onChange={(event) => update('signatureId', event.target.value)}
|
||||
options={[{ label: '不绑定签名', value: '' }, ...availableSignatures.map((signature) => ({ label: signature.name, value: signature.id }))]}
|
||||
onChange={(event) => selectSignature(event.target.value)}
|
||||
options={[{ label: '请选择签名', value: '' }, ...availableSignatures.map((signature) => ({ label: signature.name, value: signature.id }))]}
|
||||
required
|
||||
value={form.signatureId}
|
||||
/>
|
||||
<Input label="模板名称" onChange={(event) => update('name', event.target.value)} placeholder="请输入模板名称" value={form.name} />
|
||||
<Input label="模板分类" onChange={(event) => update('category', event.target.value)} placeholder="行业通知/营销推广/验证码" value={form.category} />
|
||||
<Textarea label="模板内容" onChange={(event) => setContent(event.target.value)} placeholder="变量格式:${code}" ref={contentRef} rows={6} value={form.content} />
|
||||
<Textarea
|
||||
hint="模板内容必须以所选签名开头;选择或切换签名时系统会自动填入或替换完整签名,例如:【XX公司】验证码为${code}。"
|
||||
label="模板内容"
|
||||
onChange={(event) => setContent(event.target.value)}
|
||||
placeholder="请选择签名后填写正文,变量格式:${code}"
|
||||
ref={contentRef}
|
||||
required
|
||||
rows={6}
|
||||
value={form.content}
|
||||
/>
|
||||
<div className="template-form-meta">
|
||||
<button onClick={() => setVariablesOpen((current) => !current)} type="button">
|
||||
<Plus size={16} /> {variablesOpen ? '收起变量面板' : '插入变量'}
|
||||
|
||||
@@ -158,7 +158,7 @@ export function ClientUsersPage() {
|
||||
<span className="sms-send-title__icon"><Users size={22} /></span>
|
||||
<h1>用户管理</h1>
|
||||
</div>
|
||||
<Button icon={<Plus size={18} />} onClick={() => openEditor()}>添加用户</Button>
|
||||
<Button icon={<Plus size={16} />} onClick={() => openEditor()} size="sm">添加用户</Button>
|
||||
</div>
|
||||
|
||||
<div className="system-filter-row">
|
||||
|
||||
Reference in New Issue
Block a user