| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- 'use client';
- import { useState, useEffect } from 'react';
- import api from '@/lib/api';
- import { Loader2, X, AlertTriangle } from 'lucide-react';
- interface TicketModalProps {
- isOpen: boolean;
- onClose: () => void;
- onSuccess?: () => void; // 新增:成功回调,用于刷新列表
- defaultOrderId?: string;
- }
- export default function TicketModal({ isOpen, onClose, onSuccess, defaultOrderId = '' }: TicketModalProps) {
- const [loading, setLoading] = useState<boolean>(false);
- const [errorMsg, setErrorMsg] = useState<string>('');
-
- const [form, setForm] = useState({
- order_id: '',
- type: 'refund', // 对应 API Enum: refund | dispute | change_request
- reason: ''
- });
- // 初始化
- useEffect(() => {
- if (isOpen) {
- setForm({
- order_id: defaultOrderId || '',
- type: 'refund',
- reason: ''
- });
- setErrorMsg('');
- }
- }, [isOpen, defaultOrderId]);
- const handleSubmit = async (e: React.FormEvent) => {
- e.preventDefault();
- setLoading(true);
- setErrorMsg('');
- try {
- // API: /api/vas/ticket/create
- await api.post('/api/vas/ticket/create', form);
-
- // 成功处理
- if (onSuccess) onSuccess(); // 触发父组件刷新
- onClose();
-
- } catch (error: any) {
- console.error(error);
- const msg = error.response?.data?.message || '提交失败,请稍后重试';
- setErrorMsg(msg);
- } finally {
- setLoading(false);
- }
- };
- if (!isOpen) return null;
- return (
- <div className="fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6">
- <div className="fixed inset-0 bg-black/40 backdrop-blur-sm transition-opacity" onClick={onClose} />
- <div className="relative w-full max-w-lg transform overflow-hidden rounded-xl bg-white text-left shadow-2xl transition-all animate-in zoom-in duration-200">
-
- {/* Header */}
- <div className="px-6 py-4 border-b flex justify-between items-center bg-gray-50">
- <h3 className="text-lg font-bold text-gray-900">提交工单</h3>
- <button onClick={onClose} className="text-gray-400 hover:text-gray-600 transition">
- <X size={24} />
- </button>
- </div>
-
- <div className="p-6">
- {errorMsg && (
- <div className="mb-4 p-3 bg-red-50 text-red-700 text-sm rounded-lg flex items-center">
- <AlertTriangle size={16} className="mr-2 flex-shrink-0" />
- {errorMsg}
- </div>
- )}
- <form onSubmit={handleSubmit} className="space-y-5">
- <div>
- <label className="block text-xs font-bold uppercase text-gray-500 mb-1">关联订单号 <span className="text-red-500">*</span></label>
- <input
- type="text" required
- className="w-full rounded-lg border border-gray-300 py-2.5 px-3 text-gray-900 shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none text-sm bg-gray-50 focus:bg-white transition"
- value={form.order_id}
- onChange={e => setForm({ ...form, order_id: e.target.value })}
- placeholder="请输入相关的订单编号"
- />
- </div>
- <div>
- <label className="block text-xs font-bold uppercase text-gray-500 mb-1">工单类型 <span className="text-red-500">*</span></label>
- <select
- className="w-full rounded-lg border border-gray-300 py-2.5 px-3 text-gray-900 shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none text-sm bg-white"
- value={form.type}
- onChange={e => setForm({ ...form, type: e.target.value })}
- >
- {/* 仅保留 API 支持的 Enum */}
- <option value="refund">申请退款 (Refund)</option>
- <option value="dispute">交易纠纷 (Dispute)</option>
- <option value="change_request">变更请求 (Change Request)</option>
- </select>
- </div>
- <div>
- <label className="block text-xs font-bold uppercase text-gray-500 mb-1">详细描述 <span className="text-red-500">*</span></label>
- <textarea
- required
- rows={4}
- className="w-full rounded-lg border border-gray-300 py-2.5 px-3 text-gray-900 shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none text-sm resize-none"
- placeholder="请详细描述您遇到的问题,以便我们更快为您处理..."
- value={form.reason}
- onChange={e => setForm({ ...form, reason: e.target.value })}
- />
- </div>
- <div className="pt-2 flex items-center justify-end gap-3 border-t mt-6">
- <button
- type="button"
- onClick={onClose}
- className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-200 transition"
- >
- 取消
- </button>
- <button
- type="submit"
- disabled={loading}
- className="inline-flex items-center justify-center px-6 py-2 text-sm font-bold text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed shadow-md transition"
- >
- {loading ? <Loader2 className="animate-spin w-4 h-4 mr-2" /> : null}
- 提交工单
- </button>
- </div>
- </form>
- </div>
- </div>
- </div>
- );
- }
|