feat: 业务负责人下拉按部门分组显示
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- 部门Tab和客户Tab的业务负责人下拉用optgroup按部门分组 - 顺序:部门名称作为组标题,组内显示该部门的负责人列表 - 部门排序与部门Tab一致(业务一部→二部→...→公务车) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
22
src/App.tsx
22
src/App.tsx
@@ -407,6 +407,7 @@ export default function App() {
|
|||||||
|
|
||||||
// Derived data for dept section
|
// Derived data for dept section
|
||||||
const allManagersList = useMemo(() => deptData.flatMap((d) => d.managers.map((m) => m.manager)).filter((v, i, a) => a.indexOf(v) === i).sort(), [deptData]);
|
const allManagersList = useMemo(() => deptData.flatMap((d) => d.managers.map((m) => m.manager)).filter((v, i, a) => a.indexOf(v) === i).sort(), [deptData]);
|
||||||
|
const managersGroupedByDept = useMemo(() => deptData.map((d) => ({ department: d.department, managers: d.managers.map((m) => m.manager) })), [deptData]);
|
||||||
const managerStats = useMemo(() => deptData
|
const managerStats = useMemo(() => deptData
|
||||||
.flatMap((d) => d.managers)
|
.flatMap((d) => d.managers)
|
||||||
.filter((m) => selectedManager === 'All' || m.manager === selectedManager)
|
.filter((m) => selectedManager === 'All' || m.manager === selectedManager)
|
||||||
@@ -427,6 +428,15 @@ export default function App() {
|
|||||||
const uniqueCities = useMemo(() => Array.from(new Set(customerData.map((s) => s.city).filter(Boolean))), [customerData]);
|
const uniqueCities = useMemo(() => Array.from(new Set(customerData.map((s) => s.city).filter(Boolean))), [customerData]);
|
||||||
const uniqueCustomerNames = useMemo(() => Array.from(new Set(customerData.map((s) => s.customer).filter(Boolean))), [customerData]);
|
const uniqueCustomerNames = useMemo(() => Array.from(new Set(customerData.map((s) => s.customer).filter(Boolean))), [customerData]);
|
||||||
const uniqueCustomerManagers = useMemo(() => Array.from(new Set(customerData.map((s) => s.manager).filter(Boolean))), [customerData]);
|
const uniqueCustomerManagers = useMemo(() => Array.from(new Set(customerData.map((s) => s.manager).filter(Boolean))), [customerData]);
|
||||||
|
const customerManagersGroupedByDept = useMemo(() => {
|
||||||
|
const deptMap = new Map<string, Set<string>>();
|
||||||
|
for (const s of customerData) {
|
||||||
|
if (!s.manager || !s.department) continue;
|
||||||
|
if (!deptMap.has(s.department)) deptMap.set(s.department, new Set());
|
||||||
|
deptMap.get(s.department)!.add(s.manager);
|
||||||
|
}
|
||||||
|
return Array.from(deptMap.entries()).map(([dept, mgrs]) => ({ department: dept, managers: Array.from(mgrs) }));
|
||||||
|
}, [customerData]);
|
||||||
const uniqueInventoryModels = useMemo(() => Array.from(new Set(inventoryData.map((s) => s.model).filter(Boolean))), [inventoryData]);
|
const uniqueInventoryModels = useMemo(() => Array.from(new Set(inventoryData.map((s) => s.model).filter(Boolean))), [inventoryData]);
|
||||||
const uniqueModalPlates = useMemo(() => Array.from(new Set(modalVehicles.map(v => v.plateNumber || v.vin).filter(Boolean))), [modalVehicles]);
|
const uniqueModalPlates = useMemo(() => Array.from(new Set(modalVehicles.map(v => v.plateNumber || v.vin).filter(Boolean))), [modalVehicles]);
|
||||||
const uniqueModalModels = useMemo(() => Array.from(new Set(modalVehicles.map(v => v.model).filter(Boolean))), [modalVehicles]);
|
const uniqueModalModels = useMemo(() => Array.from(new Set(modalVehicles.map(v => v.model).filter(Boolean))), [modalVehicles]);
|
||||||
@@ -1422,8 +1432,10 @@ export default function App() {
|
|||||||
className="w-full pl-9 pr-8 py-1.5 bg-white border border-gray-200 rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm appearance-none cursor-pointer font-bold text-gray-700"
|
className="w-full pl-9 pr-8 py-1.5 bg-white border border-gray-200 rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm appearance-none cursor-pointer font-bold text-gray-700"
|
||||||
>
|
>
|
||||||
<option value="All">所有业务负责人</option>
|
<option value="All">所有业务负责人</option>
|
||||||
{allManagersList.map(m => (
|
{managersGroupedByDept.map(g => (
|
||||||
<option key={m} value={m}>{m}</option>
|
<optgroup key={g.department} label={g.department}>
|
||||||
|
{g.managers.map(m => <option key={m} value={m}>{m}</option>)}
|
||||||
|
</optgroup>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
<ChevronDown className="absolute right-2.5 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none" size={14} />
|
<ChevronDown className="absolute right-2.5 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none" size={14} />
|
||||||
@@ -2270,7 +2282,11 @@ export default function App() {
|
|||||||
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider">业务负责人</label>
|
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider">业务负责人</label>
|
||||||
<select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={customerFilters.manager} onChange={(e) => setCustomerFilters(prev => ({ ...prev, manager: e.target.value }))}>
|
<select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={customerFilters.manager} onChange={(e) => setCustomerFilters(prev => ({ ...prev, manager: e.target.value }))}>
|
||||||
<option value="">所有负责人</option>
|
<option value="">所有负责人</option>
|
||||||
{uniqueCustomerManagers.map(m => <option key={m} value={m}>{m}</option>)}
|
{customerManagersGroupedByDept.map(g => (
|
||||||
|
<optgroup key={g.department} label={g.department}>
|
||||||
|
{g.managers.map(m => <option key={m} value={m}>{m}</option>)}
|
||||||
|
</optgroup>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user