Update App.jsx via upload script - 2026-08-01 18:38:24

This commit is contained in:
mike 2026-08-01 18:38:46 +08:00
parent 05feb6f523
commit dec748931a
1 changed files with 30 additions and 17 deletions

47
App.jsx
View File

@ -1902,6 +1902,7 @@ function MainApp({ username, onLogout }) {
const [dragCustomerIdx, setDragCustomerIdx] = useState(null); const [dragCustomerIdx, setDragCustomerIdx] = useState(null);
const [dragGroupState, setDragGroupState] = useState(null); // { category, index } const [dragGroupState, setDragGroupState] = useState(null); // { category, index }
const [dragJmsIdx, setDragJmsIdx] = useState(null);
const [pwCurrent, setPwCurrent] = useState(''); const [pwCurrent, setPwCurrent] = useState('');
const [pwNew, setPwNew] = useState(''); const [pwNew, setPwNew] = useState('');
@ -2067,6 +2068,11 @@ function MainApp({ username, onLogout }) {
setCustomers(prev => reorderArray(prev, dragCustomerIdx, dropIdx)); setCustomers(prev => reorderArray(prev, dragCustomerIdx, dropIdx));
setDragCustomerIdx(null); setDragCustomerIdx(null);
} }
function handleJmsDrop(dropIdx) {
if (dragJmsIdx === null || dragJmsIdx === dropIdx) { setDragJmsIdx(null); return; }
setJmsLines(prev => reorderArray(prev, dragJmsIdx, dropIdx));
setDragJmsIdx(null);
}
async function handleAddCatalogFile(file) { async function handleAddCatalogFile(file) {
if (!file) return; if (!file) return;
const tempId = 'catdoc_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6); const tempId = 'catdoc_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
@ -3142,6 +3148,10 @@ function MainApp({ username, onLogout }) {
onDelete={deleteJmsLine} onDelete={deleteJmsLine}
onCheck={checkJmsLineNow} onCheck={checkJmsLineNow}
onNotify={notify} onNotify={notify}
dragIdx={dragJmsIdx}
onDragStart={setDragJmsIdx}
onDrop={handleJmsDrop}
onDragEnd={() => setDragJmsIdx(null)}
/> />
)} )}
@ -4228,7 +4238,7 @@ const JMS_PROTO_META = {
'vless-reality': { label: 'VLESS Reality' }, 'vless-reality': { label: 'VLESS Reality' },
'vless-cdn': { label: 'VLESS CDN' }, 'vless-cdn': { label: 'VLESS CDN' },
}; };
const JMS_PROTOCOLS = ['ss', 'vmess', 'vless-reality']; const JMS_PROTOCOLS = ['ss', 'vless-reality'];
function jmsTimeAgo(ts) { function jmsTimeAgo(ts) {
if (!ts) return '尚未检测'; if (!ts) return '尚未检测';
@ -4279,7 +4289,7 @@ async function jmsResolveIp(domain) {
return answer ? answer.data : null; return answer ? answer.data : null;
} }
function JmsLineCard({ line, ip, onRefreshIp, onCheck, onCopy, onQr, onDuplicate, onEdit, onDelete }) { function JmsLineCard({ line, ip, onRefreshIp, onCheck, onCopy, onQr, onDuplicate, onEdit, onDelete, dragging, onCardDragStart, onCardDragOver, onCardDrop, onCardDragEnd }) {
const meta = JMS_PROTO_META[line.protocol]; const meta = JMS_PROTO_META[line.protocol];
const status = line.monitorStatus || 'normal'; const status = line.monitorStatus || 'normal';
const dotClass = status === 'abnormal' ? 'jms-dot-abnormal' : status === 'checking' ? 'jms-dot-checking' : 'jms-dot-normal'; const dotClass = status === 'abnormal' ? 'jms-dot-abnormal' : status === 'checking' ? 'jms-dot-checking' : 'jms-dot-normal';
@ -4288,12 +4298,21 @@ function JmsLineCard({ line, ip, onRefreshIp, onCheck, onCopy, onQr, onDuplicate
const checkNote = isVlessCdn const checkNote = isVlessCdn
? '检测方式TCP端口连通性测试HTTP状态码/WS握手结果仅作为附加参考不参与判定' ? '检测方式TCP端口连通性测试HTTP状态码/WS握手结果仅作为附加参考不参与判定'
: '检测方式TCP端口连通性测试'; : '检测方式TCP端口连通性测试';
const ipDisplay = ip === 'resolving' ? '解析中…' : (ip || '点击右侧刷新解析'); const ipDisplay = ip === 'resolving' ? '解析中…' : (ip || '试试解析当前IP');
return ( return (
<div className="jms-card"> <div
className={`jms-card ${dragging ? 'jms-card-dragging' : ''}`}
style={{ opacity: dragging ? 0.5 : 1 }}
draggable
onDragStart={onCardDragStart}
onDragOver={onCardDragOver}
onDrop={onCardDrop}
onDragEnd={onCardDragEnd}
>
<div className="jms-card-top"> <div className="jms-card-top">
<div className="jms-card-title"> <div className="jms-card-title">
<GripVertical size={14} className="drag-handle" />
<span className={`jms-dot ${dotClass}`} /> <span className={`jms-dot ${dotClass}`} />
<span className="jms-card-name">{line.name || line.addr}</span> <span className="jms-card-name">{line.name || line.addr}</span>
</div> </div>
@ -4350,14 +4369,6 @@ function JmsLineFormFields({ group, protocol, draft, setDraft }) {
</div> </div>
); );
} }
if (protocol === 'vmess') {
return (
<div className="grid-2">
<div className="field"><span className="field-label">UUID</span><input className="input" value={draft.uuid || ''} onChange={e => set({ uuid: e.target.value })} placeholder="用户UUID" /></div>
<div className="field"><span className="field-label">AlterId</span><input className="input" value={draft.alterId || '0'} onChange={e => set({ alterId: e.target.value })} /></div>
</div>
);
}
if (protocol === 'vless-reality') { if (protocol === 'vless-reality') {
return ( return (
<> <>
@ -4377,7 +4388,7 @@ function JmsLineFormFields({ group, protocol, draft, setDraft }) {
return null; return null;
} }
function JmsPage({ lines, onSave, onDelete, onCheck, onNotify }) { function JmsPage({ lines, onSave, onDelete, onCheck, onNotify, dragIdx, onDragStart, onDrop, onDragEnd }) {
const [ipMap, setIpMap] = useState({}); const [ipMap, setIpMap] = useState({});
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const [editingId, setEditingId] = useState(null); const [editingId, setEditingId] = useState(null);
@ -4389,7 +4400,6 @@ function JmsPage({ lines, onSave, onDelete, onCheck, onNotify }) {
const total = lines.length; const total = lines.length;
const ssCount = lines.filter(l => l.protocol === 'ss').length; const ssCount = lines.filter(l => l.protocol === 'ss').length;
const vmessCount = lines.filter(l => l.protocol === 'vmess').length;
const vlessCount = lines.filter(l => l.protocol.startsWith('vless')).length; const vlessCount = lines.filter(l => l.protocol.startsWith('vless')).length;
async function refreshIp(id, addr) { async function refreshIp(id, addr) {
@ -4468,7 +4478,6 @@ function JmsPage({ lines, onSave, onDelete, onCheck, onNotify }) {
<div className="page-head-row"> <div className="page-head-row">
<div> <div>
<h2 className="crm-display" style={{ fontSize: 22, fontWeight: 700, margin: '0 0 4px' }}>Just My Socks 节点管理</h2> <h2 className="crm-display" style={{ fontSize: 22, fontWeight: 700, margin: '0 0 4px' }}>Just My Socks 节点管理</h2>
<div className="disclaimer" style={{ marginBottom: 0 }}>管理自建VLESS-CDN线路和 justmysocks2.net 订阅线路 · DNS解析订阅链接二维码和连通性监控</div>
</div> </div>
<button className="btn btn-primary" onClick={openAddModal}><Plus size={14} />新增线路</button> <button className="btn btn-primary" onClick={openAddModal}><Plus size={14} />新增线路</button>
</div> </div>
@ -4476,13 +4485,12 @@ function JmsPage({ lines, onSave, onDelete, onCheck, onNotify }) {
<div className="jms-stats-row"> <div className="jms-stats-row">
<div className="stat-chip"><div className="stat-num">{total}</div><div className="stat-lbl">线路总数</div></div> <div className="stat-chip"><div className="stat-num">{total}</div><div className="stat-lbl">线路总数</div></div>
<div className="stat-chip"><div className="stat-num">{ssCount}</div><div className="stat-lbl">SS</div></div> <div className="stat-chip"><div className="stat-num">{ssCount}</div><div className="stat-lbl">SS</div></div>
<div className="stat-chip"><div className="stat-num">{vmessCount}</div><div className="stat-lbl">VMess</div></div>
<div className="stat-chip"><div className="stat-num">{vlessCount}</div><div className="stat-lbl">VLESS</div></div> <div className="stat-chip"><div className="stat-num">{vlessCount}</div><div className="stat-lbl">VLESS</div></div>
</div> </div>
<div className="jms-grid"> <div className="jms-grid">
{lines.length === 0 && <div className="empty-state" style={{ gridColumn: '1/-1' }}><Wifi size={28} />还没有线路点右上角"新增线路"添加</div>} {lines.length === 0 && <div className="empty-state" style={{ gridColumn: '1/-1' }}><Wifi size={28} />还没有线路点右上角"新增线路"添加</div>}
{lines.map(line => ( {lines.map((line, idx) => (
<JmsLineCard <JmsLineCard
key={line.id} key={line.id}
line={line} line={line}
@ -4494,6 +4502,11 @@ function JmsPage({ lines, onSave, onDelete, onCheck, onNotify }) {
onDuplicate={duplicateLine} onDuplicate={duplicateLine}
onEdit={openEditModal} onEdit={openEditModal}
onDelete={onDelete} onDelete={onDelete}
dragging={dragIdx === idx}
onCardDragStart={() => onDragStart(idx)}
onCardDragOver={(e) => e.preventDefault()}
onCardDrop={() => onDrop(idx)}
onCardDragEnd={onDragEnd}
/> />
))} ))}
</div> </div>