Merge asset statistics and contextual AI assistant into main
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import React, { lazy, Suspense, useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||
import {
|
||||
Truck,
|
||||
Sparkles,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
Loader2,
|
||||
@@ -315,17 +316,21 @@ export default function AssetsModule() {
|
||||
};
|
||||
|
||||
const toggleInventoryRegion = (region: string) => {
|
||||
const newSet = new Set(expandedInventoryRegions);
|
||||
if (newSet.has(region)) newSet.delete(region);
|
||||
else newSet.add(region);
|
||||
setExpandedInventoryRegions(newSet);
|
||||
setExpandedInventoryRegions(current => {
|
||||
const next = new Set(current);
|
||||
if (next.has(region)) next.delete(region);
|
||||
else next.add(region);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
const toggleInventoryType = (type: string) => {
|
||||
const newSet = new Set(expandedInventoryTypes);
|
||||
if (newSet.has(type)) newSet.delete(type);
|
||||
else newSet.add(type);
|
||||
setExpandedInventoryTypes(newSet);
|
||||
setExpandedInventoryTypes(current => {
|
||||
const next = new Set(current);
|
||||
if (next.has(type)) next.delete(type);
|
||||
else next.add(type);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
const inventoryTypeFilter = isInventoryFilterOpen
|
||||
@@ -476,8 +481,6 @@ export default function AssetsModule() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[var(--app-bg)] text-gray-800 font-sans p-3 md:p-6 relative">
|
||||
<AssetsHeader
|
||||
assistantTrigger={assistantTrigger}
|
||||
onOpenAssistant={() => setAssistantOpen(true)}
|
||||
activeTab={activeTab}
|
||||
setActiveTab={setActiveTab}
|
||||
theme={theme}
|
||||
@@ -1701,6 +1704,18 @@ export default function AssetsModule() {
|
||||
|
||||
</div>
|
||||
<RotatingFooterHint className="pb-4" />
|
||||
<button
|
||||
ref={assistantTrigger}
|
||||
type="button"
|
||||
onClick={() => setAssistantOpen(true)}
|
||||
aria-label="打开 AI 问数"
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded={assistantOpen}
|
||||
className="fixed bottom-[calc(5rem+env(safe-area-inset-bottom))] right-4 z-[60] inline-flex min-h-12 items-center gap-2 rounded-full bg-gradient-to-br from-blue-600 to-cyan-500 px-4 text-sm font-semibold text-white shadow-lg shadow-blue-200 transition hover:from-blue-700 hover:to-cyan-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 md:bottom-6 md:right-6"
|
||||
>
|
||||
<Sparkles size={20} aria-hidden="true" />
|
||||
AI 问数
|
||||
</button>
|
||||
{assistantOpen && <Suspense fallback={<div role="status" className="fixed bottom-20 right-6 z-50 rounded-xl bg-white p-4 text-slate-900 shadow-lg">正在打开 AI 问数…</div>}><AssetAssistant key={selectedSubject || 'all'} subject={selectedSubject} appearance="light" close={() => { setAssistantOpen(false); requestAnimationFrame(() => assistantTrigger.current?.focus()); }} /></Suspense>}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user