diff --git a/App.jsx b/App.jsx index ea7cce3..979d477 100644 --- a/App.jsx +++ b/App.jsx @@ -13,7 +13,7 @@ import { getAiConfig, saveAiConfig, deleteAiConfig, testAiConfig, generateAiDraft, parseCatalogFiles, translateTerms, getTelegramConfig, saveTelegramConfig, deleteTelegramConfig, testTelegramConfig, - checkJmsLine, fetchJmsTraffic, + checkJmsLine, } from './storage'; /* ----------------------------- constants ----------------------------- */ @@ -248,7 +248,7 @@ const COUNTRIES = [ const COUNTRY_BY_NAME = Object.fromEntries(COUNTRIES.map(c => [c.name, c])); -const STORAGE_KEYS = { customers: 'crm:customers', products: 'crm:products', settings: 'crm:settings', quotes: 'crm:quotes', sellerProfiles: 'crm:sellerProfiles', certifications: 'crm:certifications', productCategories: 'crm:productCategories', packingLists: 'crm:packingLists', catalogDocs: 'crm:catalogDocs', jmsLines: 'crm:jmsLines', jmsSubUrl: 'crm:jmsSubUrl' }; +const STORAGE_KEYS = { customers: 'crm:customers', products: 'crm:products', settings: 'crm:settings', quotes: 'crm:quotes', sellerProfiles: 'crm:sellerProfiles', certifications: 'crm:certifications', productCategories: 'crm:productCategories', packingLists: 'crm:packingLists', catalogDocs: 'crm:catalogDocs', jmsLines: 'crm:jmsLines' }; const blankCustomer = () => ({ id: 'c_' + Date.now() + '_' + Math.random().toString(36).slice(2, 7), @@ -1266,16 +1266,11 @@ async function loadAll() { if (cd && cd.value) catalogDocs = JSON.parse(cd.value); } catch (e) {} let jmsLines = []; - let jmsSubUrl = ''; try { const jl = await storageGet(STORAGE_KEYS.jmsLines); if (jl && jl.value) jmsLines = JSON.parse(jl.value); } catch (e) {} - try { - const ju = await storageGet(STORAGE_KEYS.jmsSubUrl); - if (ju && ju.value) jmsSubUrl = ju.value; - } catch (e) {} - return { customers, products, settings, quotes, sellerProfiles, certifications, productCategories, packingLists, catalogDocs, jmsLines, jmsSubUrl }; + return { customers, products, settings, quotes, sellerProfiles, certifications, productCategories, packingLists, catalogDocs, jmsLines }; } /* -------------------------------- styles -------------------------------- */ @@ -1413,21 +1408,6 @@ const Styles = () => ( .stat-num { font-family: 'Space Grotesk', sans-serif; font-size: 22px; font-weight: 700; } .stat-lbl { font-size: 11.5px; color: var(--ink-soft); } - .jms-traffic-widget { position: relative; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 16px; min-width: 252px; display: flex; flex-direction: column; gap: 6px; justify-content: center; } - .jms-traffic-top { display: flex; align-items: center; gap: 6px; } - .jms-traffic-title { font-size: 11.5px; font-weight: 700; color: var(--ink-soft); } - .jms-traffic-badge { font-size: 9.5px; font-weight: 600; color: var(--copper); background: var(--copper-soft); padding: 2px 7px; border-radius: 100px; } - .jms-icon-btn { margin-left: 0; background: none; border: none; color: var(--ink-soft); cursor: pointer; padding: 2px; display: flex; border-radius: 4px; } - .jms-icon-btn:last-child { margin-left: auto; } - .jms-icon-btn:hover { background: var(--bg); color: var(--ink); } - .jms-traffic-bar { height: 6px; background: var(--line); border-radius: 100px; overflow: hidden; } - .jms-traffic-bar-fill { height: 100%; background: linear-gradient(90deg, var(--copper), #D08A44); border-radius: 100px; transition: width .4s; } - .jms-traffic-meta { font-family: 'IBM Plex Mono', monospace; font-size: 12px; font-weight: 600; color: var(--ink); } - .jms-traffic-settings { - position: absolute; top: calc(100% + 6px); right: 0; z-index: 20; background: var(--panel); - border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; box-shadow: 0 8px 24px rgba(0,0,0,0.12); width: 260px; - } - .jms-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; } .jms-card { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 16px 16px 14px; display: flex; flex-direction: column; gap: 12px; } .jms-card-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; } @@ -1965,9 +1945,6 @@ function MainApp({ username, onLogout }) { const [catalogEditDraft, setCatalogEditDraft] = useState({ title: '', category: '', brand: '', type: '' }); const [catalogCategoryFilter, setCatalogCategoryFilter] = useState('all'); const [jmsLines, setJmsLines] = useState([]); - const [jmsSubUrl, setJmsSubUrl] = useState(''); - const [jmsTraffic, setJmsTraffic] = useState(null); // { upload, download, total, expire } 或 null(还没拉取过) - const [jmsTrafficLoading, setJmsTrafficLoading] = useState(false); const [telegramConfigHasToken, setTelegramConfigHasToken] = useState(false); const [telegramConfigChatId, setTelegramConfigChatId] = useState(''); @@ -1994,7 +1971,6 @@ function MainApp({ username, onLogout }) { setPackingLists(data.packingLists); setCatalogDocs((data.catalogDocs || []).filter(d => d.fileName)); setJmsLines(data.jmsLines || []); - setJmsSubUrl(data.jmsSubUrl || ''); setLoaded(true); })(); }, []); @@ -2014,7 +1990,6 @@ function MainApp({ username, onLogout }) { useEffect(() => { if (loaded) storageSet(STORAGE_KEYS.packingLists, JSON.stringify(packingLists)).catch(() => {}); }, [packingLists, loaded]); useEffect(() => { if (loaded) storageSet(STORAGE_KEYS.catalogDocs, JSON.stringify(catalogDocs)).catch(() => {}); }, [catalogDocs, loaded]); useEffect(() => { if (loaded) storageSet(STORAGE_KEYS.jmsLines, JSON.stringify(jmsLines)).catch(() => {}); }, [jmsLines, loaded]); - useEffect(() => { if (loaded) storageSet(STORAGE_KEYS.jmsSubUrl, jmsSubUrl).catch(() => {}); }, [jmsSubUrl, loaded]); function notify(msg) { setToast(msg); setTimeout(() => setToast(''), 2200); } @@ -2424,20 +2399,6 @@ function MainApp({ username, onLogout }) { } } - async function refreshJmsTraffic() { - if (!jmsSubUrl.trim()) { notify('请先在流量小组件的设置里填写标准订阅地址'); return; } - setJmsTrafficLoading(true); - try { - const res = await fetchJmsTraffic(jmsSubUrl.trim()); - if (res.ok) setJmsTraffic(res); - else notify(res.error || '获取流量信息失败'); - } catch (e) { - notify('获取流量信息失败:' + e.message); - } finally { - setJmsTrafficLoading(false); - } - } - async function saveTelegramSettings(botToken, chatId) { try { await saveTelegramConfig(botToken, chatId); @@ -3180,11 +3141,6 @@ function MainApp({ username, onLogout }) { onSave={saveJmsLine} onDelete={deleteJmsLine} onCheck={checkJmsLineNow} - subUrl={jmsSubUrl} - onSubUrlChange={setJmsSubUrl} - traffic={jmsTraffic} - trafficLoading={jmsTrafficLoading} - onRefreshTraffic={refreshJmsTraffic} onNotify={notify} /> )} @@ -4420,7 +4376,7 @@ function JmsLineFormFields({ group, protocol, draft, setDraft }) { return null; } -function JmsPage({ lines, onSave, onDelete, onCheck, subUrl, onSubUrlChange, traffic, trafficLoading, onRefreshTraffic, onNotify }) { +function JmsPage({ lines, onSave, onDelete, onCheck, onNotify }) { const [ipMap, setIpMap] = useState({}); const [modalOpen, setModalOpen] = useState(false); const [editingId, setEditingId] = useState(null); @@ -4429,7 +4385,6 @@ function JmsPage({ lines, onSave, onDelete, onCheck, subUrl, onSubUrlChange, tra const [draft, setDraft] = useState({}); const [qrLine, setQrLine] = useState(null); const [qrDataUrl, setQrDataUrl] = useState(''); - const [subSettingsOpen, setSubSettingsOpen] = useState(false); const total = lines.length; const ssCount = lines.filter(l => l.protocol === 'ss').length; @@ -4513,30 +4468,6 @@ function JmsPage({ lines, onSave, onDelete, onCheck, subUrl, onSubUrlChange, tra