269 lines
8.7 KiB
TypeScript
269 lines
8.7 KiB
TypeScript
'use client';
|
||
|
||
import { useState, useEffect } from 'react';
|
||
import { toast } from 'sonner';
|
||
import { MessageTemplate as MessageTemplateType } from './types';
|
||
import {
|
||
MessageTemplateList,
|
||
MessageTemplateSearch,
|
||
MessageTemplateHeader,
|
||
MessageTemplateDialog,
|
||
MessageTemplateTestDialog,
|
||
MessageTemplateInfo
|
||
} from './components';
|
||
|
||
export default function MessageTemplatePage() {
|
||
const [templates, setTemplates] = useState<MessageTemplateType[]>([]);
|
||
const [searchKeyword, setSearchKeyword] = useState('');
|
||
const [typeFilter, setTypeFilter] = useState<string>('all');
|
||
const [showDialog, setShowDialog] = useState(false);
|
||
const [showTestDialog, setShowTestDialog] = useState(false);
|
||
const [editingTemplate, setEditingTemplate] = useState<MessageTemplateType | null>(null);
|
||
const [testTemplate, setTestTemplate] = useState<MessageTemplateType | null>(null);
|
||
|
||
|
||
useEffect(() => {
|
||
loadTemplates();
|
||
}, []);
|
||
|
||
const loadTemplates = () => {
|
||
// 清除旧的localStorage数据,确保使用最新的mock数据
|
||
localStorage.removeItem('smart_agriculture_message_templates');
|
||
|
||
const data = localStorage.getItem('smart_agriculture_message_templates');
|
||
if (data) {
|
||
try {
|
||
const parsedData = JSON.parse(data);
|
||
console.log('Loaded templates from localStorage:', parsedData);
|
||
// 确保数据是数组格式
|
||
if (Array.isArray(parsedData)) {
|
||
setTemplates(parsedData);
|
||
} else {
|
||
console.error('Loaded data is not an array:', parsedData);
|
||
setTemplates([]);
|
||
}
|
||
} catch (error) {
|
||
console.error('Error parsing templates from localStorage:', error);
|
||
setTemplates([]);
|
||
}
|
||
} else {
|
||
const mockTemplates: MessageTemplateType[] = [
|
||
{
|
||
id: 'tpl-1',
|
||
code: 'TASK_ASSIGNED',
|
||
name: '任务分配通知',
|
||
type: 'internal',
|
||
subject: '新任务分配',
|
||
content: '您好,{{username}}!您有新的作业任务:{{taskName}},计划执行时间:{{executeTime}}。请及时查看并准备。',
|
||
variables: ['username', 'taskName', 'executeTime'],
|
||
isActive: true,
|
||
description: '当任务分配给驾驶员时发送',
|
||
createdAt: '2024-01-01T00:00:00',
|
||
updatedAt: '2024-01-01T00:00:00',
|
||
createdBy: 'admin',
|
||
},
|
||
{
|
||
id: 'tpl-2',
|
||
code: 'EQUIPMENT_WARNING',
|
||
name: '设备预警通知',
|
||
type: 'sms',
|
||
content: '【智慧农业】设备预警:{{equipmentName}}检测到异常,{{warningType}},请及时处理。',
|
||
variables: ['equipmentName', 'warningType'],
|
||
isActive: true,
|
||
description: '设备出现异常时发送短信通知',
|
||
createdAt: '2024-01-01T00:00:00',
|
||
updatedAt: '2024-01-01T00:00:00',
|
||
createdBy: 'admin',
|
||
},
|
||
{
|
||
id: 'tpl-3',
|
||
code: 'MAINTENANCE_REMINDER',
|
||
name: '保养提醒',
|
||
type: 'email',
|
||
subject: '设备保养提醒',
|
||
content: '尊敬的用户:\n\n您的设备{{equipmentName}}(编号:{{equipmentCode}})已使用{{hours}}小时,建议进行保养维护。\n\n保养周期:{{maintenanceCycle}}\n上次保养时间:{{lastMaintenanceTime}}\n\n请及时安排保养,确保设备正常运行。\n\n智慧农业管理系统',
|
||
variables: ['equipmentName', 'equipmentCode', 'hours', 'maintenanceCycle', 'lastMaintenanceTime'],
|
||
isActive: true,
|
||
description: '设备到达保养周期时发送邮件提醒',
|
||
createdAt: '2024-01-01T00:00:00',
|
||
updatedAt: '2024-01-01T00:00:00',
|
||
createdBy: 'admin',
|
||
},
|
||
{
|
||
id: 'tpl-4',
|
||
code: 'TASK_COMPLETED',
|
||
name: '任务完成通知',
|
||
type: 'push',
|
||
subject: '任务完成',
|
||
content: '作业任务{{taskName}}已完成,作业面积:{{area}}亩,耗时:{{duration}}。',
|
||
variables: ['taskName', 'area', 'duration'],
|
||
isActive: true,
|
||
description: '任务完成后推送通知',
|
||
createdAt: '2024-01-01T00:00:00',
|
||
updatedAt: '2024-01-01T00:00:00',
|
||
createdBy: 'admin',
|
||
},
|
||
];
|
||
console.log('Created mock templates:', mockTemplates);
|
||
localStorage.setItem('smart_agriculture_message_templates', JSON.stringify(mockTemplates));
|
||
setTemplates(mockTemplates);
|
||
}
|
||
};
|
||
|
||
const saveTemplates = (newTemplates: MessageTemplateType[]) => {
|
||
localStorage.setItem('smart_agriculture_message_templates', JSON.stringify(newTemplates));
|
||
setTemplates(newTemplates);
|
||
};
|
||
|
||
const filteredTemplates = templates.filter(tpl => {
|
||
const matchKeyword = !searchKeyword ||
|
||
tpl.name.includes(searchKeyword) ||
|
||
tpl.code.includes(searchKeyword) ||
|
||
tpl.content.includes(searchKeyword);
|
||
const matchType = typeFilter === 'all' || tpl.type === typeFilter;
|
||
return matchKeyword && matchType;
|
||
});
|
||
|
||
// 调试日志
|
||
console.log('Original templates:', templates);
|
||
console.log('Filtered templates:', filteredTemplates);
|
||
console.log('Search keyword:', searchKeyword);
|
||
console.log('Type filter:', typeFilter);
|
||
|
||
const handleAdd = () => {
|
||
setEditingTemplate(null);
|
||
setShowDialog(true);
|
||
};
|
||
|
||
const handleEdit = (template: MessageTemplateType) => {
|
||
setEditingTemplate(template);
|
||
setShowDialog(true);
|
||
};
|
||
|
||
const handleDelete = (id: string) => {
|
||
const updated = templates.filter(t => t.id !== id);
|
||
saveTemplates(updated);
|
||
toast.success('删除成功');
|
||
};
|
||
|
||
const handleSave = (formData: any) => {
|
||
if (!formData.code.trim() || !formData.name.trim() || !formData.content.trim()) {
|
||
toast.error('请填写必填项');
|
||
return;
|
||
}
|
||
|
||
const now = new Date().toISOString();
|
||
|
||
// 提取变量
|
||
const variableRegex = /\{\{(\w+)\}\}/g;
|
||
const matches = formData.content.matchAll(variableRegex);
|
||
const extractedVars = Array.from(new Set(Array.from(matches, m => m[1])));
|
||
|
||
if (editingTemplate) {
|
||
const updated = templates.map(t =>
|
||
t.id === editingTemplate.id
|
||
? {
|
||
...t,
|
||
...formData,
|
||
variables: extractedVars,
|
||
updatedAt: now,
|
||
}
|
||
: t
|
||
);
|
||
saveTemplates(updated);
|
||
toast.success('更新成功');
|
||
} else {
|
||
const newTemplate: MessageTemplateType = {
|
||
id: `tpl-${Date.now()}`,
|
||
...formData,
|
||
variables: extractedVars,
|
||
createdAt: now,
|
||
updatedAt: now,
|
||
createdBy: 'admin',
|
||
};
|
||
saveTemplates([...templates, newTemplate]);
|
||
toast.success('添加成功');
|
||
}
|
||
|
||
setShowDialog(false);
|
||
};
|
||
|
||
const handleTest = (template: MessageTemplateType) => {
|
||
setTestTemplate(template);
|
||
setShowTestDialog(true);
|
||
};
|
||
|
||
const handleSendTest = (testData: any) => {
|
||
if (!testData.recipient.trim()) {
|
||
toast.error('请输入接收人');
|
||
return;
|
||
}
|
||
|
||
// 检查变量是否都填写了
|
||
const emptyVars = Object.entries(testData.variables).filter(([k, v]) => !v.trim());
|
||
if (emptyVars.length > 0) {
|
||
toast.error('请填写变量:' + emptyVars.map(([k]) => k).join(', '));
|
||
return;
|
||
}
|
||
|
||
toast.success('测试消息发送成功');
|
||
setShowTestDialog(false);
|
||
};
|
||
|
||
const handleExport = () => {
|
||
const dataStr = JSON.stringify(filteredTemplates, null, 2);
|
||
const dataBlob = new Blob([dataStr], { type: 'application/json' });
|
||
const url = URL.createObjectURL(dataBlob);
|
||
const link = document.createElement('a');
|
||
link.href = url;
|
||
link.download = `message_templates_${new Date().getTime()}.json`;
|
||
link.click();
|
||
toast.success('导出成功');
|
||
};
|
||
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* 页面头部 */}
|
||
<MessageTemplateHeader
|
||
onExport={handleExport}
|
||
onAdd={handleAdd}
|
||
/>
|
||
|
||
{/* 搜索和筛选 */}
|
||
<MessageTemplateSearch
|
||
searchKeyword={searchKeyword}
|
||
onSearchChange={setSearchKeyword}
|
||
typeFilter={typeFilter}
|
||
onTypeFilterChange={setTypeFilter}
|
||
/>
|
||
|
||
{/* 模版列表 */}
|
||
<MessageTemplateList
|
||
templates={filteredTemplates}
|
||
onEdit={handleEdit}
|
||
onDelete={handleDelete}
|
||
onTest={handleTest}
|
||
/>
|
||
|
||
{/* 编辑对话框 */}
|
||
<MessageTemplateDialog
|
||
open={showDialog}
|
||
onOpenChange={setShowDialog}
|
||
editingTemplate={editingTemplate}
|
||
onSave={handleSave}
|
||
/>
|
||
|
||
{/* 测试对话框 */}
|
||
<MessageTemplateTestDialog
|
||
open={showTestDialog}
|
||
onOpenChange={setShowTestDialog}
|
||
testTemplate={testTemplate}
|
||
onSendTest={handleSendTest}
|
||
/>
|
||
|
||
{/* 使用说明 */}
|
||
<MessageTemplateInfo />
|
||
</div>
|
||
);
|
||
} |