feat: 水印移到全局Shell,资产和里程页面都有水印
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, type ComponentType } from 'react';
|
||||
import { useState, useEffect, useMemo, type ComponentType } from 'react';
|
||||
import { useAuth } from '../auth/useAuth';
|
||||
|
||||
export interface ModuleConfig {
|
||||
id: string;
|
||||
@@ -55,8 +56,22 @@ export function Shell({ modules }: { modules: ModuleConfig[] }) {
|
||||
|
||||
const ActiveComponent = modules.find((m) => m.id === activeModule)?.component ?? modules[0]?.component;
|
||||
|
||||
const { user } = useAuth();
|
||||
const watermarkText = useMemo(() => {
|
||||
const name = user?.userName || '未登录';
|
||||
const time = new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-');
|
||||
return `${name}-${time}`;
|
||||
}, [user]);
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen">
|
||||
{/* 全局水印 */}
|
||||
<div className="fixed inset-0 pointer-events-none z-[9999] overflow-hidden" style={{ opacity: 0.06 }}>
|
||||
<div className="absolute inset-0" style={{
|
||||
backgroundImage: `url("data:image/svg+xml,${encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' width='320' height='200'><text x='50%' y='50%' text-anchor='middle' dominant-baseline='middle' font-size='14' font-family='sans-serif' fill='%23000' transform='rotate(-25 160 100)'>${watermarkText}</text></svg>`)}")`,
|
||||
backgroundRepeat: 'repeat',
|
||||
}} />
|
||||
</div>
|
||||
{/* Web 侧边栏 (md 及以上) */}
|
||||
<nav className="hidden md:flex flex-col items-center w-16 bg-white border-r border-gray-100 fixed top-0 left-0 h-full z-50 py-6 gap-2">
|
||||
{modules.map((m) => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||
import { useAuth } from '../../auth/useAuth';
|
||||
import {
|
||||
Truck,
|
||||
Warehouse,
|
||||
@@ -46,7 +45,6 @@ const TABS = [
|
||||
];
|
||||
|
||||
export default function AssetsModule() {
|
||||
const { user } = useAuth();
|
||||
const [activeTab, setActiveTab] = useState<'overview' | 'department' | 'region' | 'customer'>('overview');
|
||||
const [tabReady, setTabReady] = useState(true);
|
||||
const prevTabRef = useRef(activeTab);
|
||||
@@ -455,7 +453,6 @@ export default function AssetsModule() {
|
||||
}
|
||||
}, [customerData, customerChartView, customerProvinceData]);
|
||||
|
||||
const watermarkText = useMemo(() => `${user?.userName || '未登录'}-${new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-')}`, [lastUpdate, user]);
|
||||
|
||||
if (loading && !summary) {
|
||||
return (
|
||||
@@ -486,13 +483,6 @@ export default function AssetsModule() {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8F9FB] text-gray-800 font-sans p-6 relative">
|
||||
{/* Watermark */}
|
||||
<div className="fixed inset-0 pointer-events-none z-[9999] overflow-hidden" style={{ opacity: 0.06 }}>
|
||||
<div className="absolute inset-0" style={{
|
||||
backgroundImage: `url("data:image/svg+xml,${encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' width='320' height='200'><text x='50%' y='50%' text-anchor='middle' dominant-baseline='middle' font-size='14' font-family='sans-serif' fill='%23000' transform='rotate(-25 160 100)'>${watermarkText}</text></svg>`)}")`,
|
||||
backgroundRepeat: 'repeat',
|
||||
}} />
|
||||
</div>
|
||||
{/* Compact Header Bar */}
|
||||
<div className="sticky top-0 z-40 -mx-6 -mt-6 mb-4 bg-white/95 backdrop-blur-sm border-b border-gray-100/80">
|
||||
{/* Title row */}
|
||||
|
||||
Reference in New Issue
Block a user