feat: harden platform workflows and UI governance

This commit is contained in:
hectorzhao
2026-07-22 14:14:55 +08:00
parent ef957f7daa
commit 0f223f7f91
80 changed files with 4958 additions and 764 deletions
+7 -13
View File
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { Edit3, MessageSquare, Plus, Search, Trash2 } from 'lucide-react';
import { Button, Input, Modal, Pagination, Select, Tag, Textarea } from '@/components/ui';
import { Button, DeleteRiskAction, Input, Modal, Pagination, Select, Tag, Textarea } from '@/components/ui';
import { clientApi, type ClientSmsApplication, type ClientSmsSignatureView, type ClientSmsTemplate } from '@/api/adminApi';
import { formatDateTime } from '@/utils/dateTime';
import { replaceLeadingSmsSignature } from '@/utils/smsSignature';
@@ -86,6 +86,8 @@ function TemplateModal({
content: initialContent,
variables: item?.variables?.map((variable) => ({ name: variable.name, example: variable.example ?? undefined, required: variable.required ?? true })) ?? [],
});
const initialForm = useRef(form).current;
const dirty = JSON.stringify(form) !== JSON.stringify(initialForm);
const application = applications.find((candidate) => candidate.id === form.applicationId);
const availableSignatures = signatures.filter((signature) => (
signature.auditStatus === 'approved'
@@ -130,9 +132,10 @@ function TemplateModal({
return (
<Modal
footer={(
dirty={dirty}
footer={({ requestClose }) => (
<>
<Button onClick={onClose} variant="ghost"></Button>
<Button onClick={requestClose} variant="ghost"></Button>
<Button disabled={!form.applicationId || !form.signatureId || !form.name || !form.content.trim()} onClick={() => onSubmit({ ...form, variables })}></Button>
</>
)}
@@ -266,12 +269,6 @@ export function ClientTemplatesPage() {
}
}
function disableTemplate(id: string) {
clientApi.changeTemplateStatus(id, 'disabled')
.then(loadData)
.catch((reason: Error) => setError(reason.message || '模板禁用失败'));
}
return (
<section className="page-stack">
<div className="template-page-header">
@@ -315,10 +312,7 @@ export function ClientTemplatesPage() {
<Edit3 size={14} />
</button>
<button onClick={() => disableTemplate(template.id)} type="button">
<Trash2 size={14} />
</button>
<DeleteRiskAction onCompleted={() => void loadData()} portal="client" targetId={template.id} targetType="template" />
</div>
</div>
</article>