272 lines
8.5 KiB
TypeScript
272 lines
8.5 KiB
TypeScript
/**
|
|
* 支付平台模态框组件
|
|
* 作者: 阿瑞
|
|
* 功能: 提供支付平台信息的添加和编辑界面
|
|
* 版本: 1.0.0
|
|
*/
|
|
|
|
'use client';
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
import { useParams } from 'next/navigation';
|
|
import { PaymentPlatform, PaymentPlatformStatus } from '@/models/team/types/old/payment-platform';
|
|
import Modal from '@/components/ui/Modal';
|
|
|
|
interface PaymentPlatformModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
platform?: PaymentPlatform | null;
|
|
onSuccess: () => void;
|
|
}
|
|
|
|
/**
|
|
* 支付平台模态框组件
|
|
*/
|
|
export default function PaymentPlatformModal({ isOpen, onClose, platform, onSuccess }: PaymentPlatformModalProps) {
|
|
const params = useParams();
|
|
const teamCode = params?.teamCode as string;
|
|
|
|
const isEditing = !!platform;
|
|
|
|
// 表单状态
|
|
const [formData, setFormData] = useState<Partial<PaymentPlatform>>({
|
|
name: '',
|
|
order: 0,
|
|
description: '',
|
|
status: PaymentPlatformStatus.NORMAL
|
|
});
|
|
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
/**
|
|
* 初始化编辑表单数据
|
|
*/
|
|
useEffect(() => {
|
|
if (platform) {
|
|
setFormData({
|
|
id: platform.id,
|
|
name: platform.name,
|
|
order: platform.order,
|
|
description: platform.description || '',
|
|
status: platform.status
|
|
});
|
|
} else {
|
|
// 重置表单
|
|
setFormData({
|
|
name: '',
|
|
order: 0,
|
|
description: '',
|
|
status: PaymentPlatformStatus.NORMAL
|
|
});
|
|
}
|
|
|
|
setError(null);
|
|
}, [platform, isOpen]);
|
|
|
|
/**
|
|
* 处理表单输入变化
|
|
*/
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
|
const { name, value } = e.target;
|
|
|
|
// 处理数字类型字段
|
|
if (name === 'order') {
|
|
setFormData(prev => ({
|
|
...prev,
|
|
[name]: value === '' ? 0 : parseInt(value, 10)
|
|
}));
|
|
return;
|
|
}
|
|
|
|
// 处理状态选择
|
|
if (name === 'status') {
|
|
setFormData(prev => ({
|
|
...prev,
|
|
[name]: parseInt(value, 10)
|
|
}));
|
|
return;
|
|
}
|
|
|
|
setFormData(prev => ({
|
|
...prev,
|
|
[name]: value
|
|
}));
|
|
};
|
|
|
|
/**
|
|
* 提交表单
|
|
*/
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
|
|
// 基本验证
|
|
if (!formData.name) {
|
|
setError('平台名称为必填项');
|
|
return;
|
|
}
|
|
|
|
if (formData.order === undefined || formData.order < 0) {
|
|
setError('显示顺序必须为非负整数');
|
|
return;
|
|
}
|
|
|
|
setIsSubmitting(true);
|
|
setError(null);
|
|
|
|
try {
|
|
let response;
|
|
|
|
if (isEditing && platform) {
|
|
// 更新支付平台
|
|
response = await fetch(`/api/team/${teamCode}/payment-platforms/${platform.id}`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(formData)
|
|
});
|
|
} else {
|
|
// 创建支付平台
|
|
response = await fetch(`/api/team/${teamCode}/payment-platforms`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(formData)
|
|
});
|
|
}
|
|
|
|
// 处理响应
|
|
const result = await response.json();
|
|
|
|
if (!response.ok) {
|
|
throw new Error(result.error || '操作失败');
|
|
}
|
|
|
|
// 成功处理
|
|
onSuccess();
|
|
onClose();
|
|
} catch (err) {
|
|
console.error('提交支付平台数据失败:', err);
|
|
setError(err instanceof Error ? err.message : '未知错误');
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
isOpen={isOpen}
|
|
onClose={onClose}
|
|
title={isEditing ? '编辑支付平台' : '添加支付平台'}
|
|
>
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
{/* 错误提示 */}
|
|
{error && (
|
|
<div className="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4">
|
|
<p>{error}</p>
|
|
</div>
|
|
)}
|
|
|
|
{/* 平台名称 */}
|
|
<div>
|
|
<label htmlFor="name" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
平台名称 <span className="text-red-500">*</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="name"
|
|
name="name"
|
|
value={formData.name}
|
|
onChange={handleChange}
|
|
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
{/* 显示顺序 */}
|
|
<div>
|
|
<label htmlFor="order" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
显示顺序 <span className="text-red-500">*</span>
|
|
</label>
|
|
<input
|
|
type="number"
|
|
id="order"
|
|
name="order"
|
|
value={formData.order}
|
|
onChange={handleChange}
|
|
min="0"
|
|
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
|
required
|
|
/>
|
|
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">数字越小排序越靠前</p>
|
|
</div>
|
|
|
|
{/* 平台状态 */}
|
|
<div>
|
|
<label htmlFor="status" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
平台状态
|
|
</label>
|
|
<select
|
|
id="status"
|
|
name="status"
|
|
value={formData.status}
|
|
onChange={handleChange}
|
|
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
|
>
|
|
<option value={PaymentPlatformStatus.NORMAL}>正常</option>
|
|
<option value={PaymentPlatformStatus.DISABLED}>停用</option>
|
|
<option value={PaymentPlatformStatus.BACKUP}>备用</option>
|
|
<option value={PaymentPlatformStatus.OTHER}>其他</option>
|
|
</select>
|
|
</div>
|
|
|
|
{/* 平台描述 */}
|
|
<div>
|
|
<label htmlFor="description" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
平台描述
|
|
</label>
|
|
<textarea
|
|
id="description"
|
|
name="description"
|
|
value={formData.description || ''}
|
|
onChange={handleChange}
|
|
rows={3}
|
|
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
|
/>
|
|
</div>
|
|
|
|
{/* 表单按钮 */}
|
|
<div className="flex justify-end space-x-3 pt-3">
|
|
<button
|
|
type="button"
|
|
onClick={onClose}
|
|
className="px-4 py-2 text-sm font-medium text-gray-700 bg-white dark:bg-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none"
|
|
>
|
|
取消
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
disabled={isSubmitting}
|
|
className={`px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md shadow-sm hover:bg-blue-700 focus:outline-none ${
|
|
isSubmitting ? 'opacity-70 cursor-not-allowed' : ''
|
|
}`}
|
|
>
|
|
{isSubmitting ? (
|
|
<span className="flex items-center">
|
|
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
</svg>
|
|
处理中...
|
|
</span>
|
|
) : (
|
|
isEditing ? '保存' : '创建'
|
|
)}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</Modal>
|
|
);
|
|
}
|