生产管理系统前端 - 瓦力0.71原型图更新

This commit is contained in:
2025-10-28 15:26:08 +08:00
parent 26213aaa76
commit b907cc4299
68 changed files with 14479 additions and 285 deletions

View File

@@ -235,7 +235,7 @@ export function Navigation({ activeTab, onTabChange, onMessageClick, onProfileCl
messages.map((msg) => (
<div
key={msg.id}
className="p-4 border-b hover:bg-gray-50 cursor-pointer transition-colors"
className="p-4 border-b hover:bg-accent cursor-pointer transition-colors"
onClick={() => handleMessageItemClick(msg)}
>
<div className="flex items-start gap-3">

View File

@@ -1071,21 +1071,21 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
</div>
<div className="grid grid-cols-4 gap-4 mb-3">
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="text-sm font-medium">
{rule.condition.metric} {rule.condition.operator === 'gt' ? '>' : '<'} {rule.condition.threshold}
</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="text-sm font-medium">{rule.condition.duration}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="text-sm font-medium">{rule.triggeredCount}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="text-sm font-medium">{rule.lastTriggered || '从未'}</div>
</div>
@@ -1214,19 +1214,19 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
<div>
<h4 className="mb-3"></h4>
<div className="grid grid-cols-2 gap-4">
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedAlert.alertNo}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedAlert.ruleName}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div>{getLevelBadge(selectedAlert.level)}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div>{getStatusBadge(selectedAlert.status)}</div>
</div>
@@ -1249,15 +1249,15 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
<div>
<h4 className="mb-3"></h4>
<div className="grid grid-cols-3 gap-4">
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedAlert.triggerValue}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedAlert.threshold}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedAlert.triggerTime}</div>
</div>
@@ -1544,7 +1544,7 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
{/* 根据条件类型显示不同的配置 */}
{triggerConditionType === 'response_time' && (
<div className="p-4 bg-gray-50 rounded-lg space-y-3">
<div className="p-4 bg-muted rounded-lg space-y-3">
<div className="grid grid-cols-2 gap-4">
<div>
<Label> (ms)</Label>
@@ -1562,7 +1562,7 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
)}
{triggerConditionType === 'service_exception' && (
<div className="p-4 bg-gray-50 rounded-lg space-y-3">
<div className="p-4 bg-muted rounded-lg space-y-3">
<div className="grid grid-cols-2 gap-4">
<div>
<Label></Label>
@@ -1590,7 +1590,7 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
)}
{triggerConditionType === 'decision_failure' && (
<div className="p-4 bg-gray-50 rounded-lg space-y-3">
<div className="p-4 bg-muted rounded-lg space-y-3">
<div className="grid grid-cols-2 gap-4">
<div>
<Label> (%)</Label>
@@ -1623,7 +1623,7 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
)}
{triggerConditionType === 'data_quality' && (
<div className="p-4 bg-gray-50 rounded-lg space-y-3">
<div className="p-4 bg-muted rounded-lg space-y-3">
<div className="grid grid-cols-2 gap-4">
<div>
<Label></Label>
@@ -1658,7 +1658,7 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
)}
{(triggerConditionType === 'cpu_usage' || triggerConditionType === 'memory_usage') && (
<div className="p-4 bg-gray-50 rounded-lg space-y-3">
<div className="p-4 bg-muted rounded-lg space-y-3">
<div className="grid grid-cols-2 gap-4">
<div>
<Label>使 (%)</Label>
@@ -1676,7 +1676,7 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
)}
{triggerConditionType === 'error_rate' && (
<div className="p-4 bg-gray-50 rounded-lg space-y-3">
<div className="p-4 bg-muted rounded-lg space-y-3">
<div className="grid grid-cols-2 gap-4">
<div>
<Label> (%)</Label>
@@ -1694,7 +1694,7 @@ export function AIAlertManagement({ activePath }: AIAlertManagementProps) {
)}
{triggerConditionType === 'request_count' && (
<div className="p-4 bg-gray-50 rounded-lg space-y-3">
<div className="p-4 bg-muted rounded-lg space-y-3">
<div className="grid grid-cols-2 gap-4">
<div>
<Label></Label>

View File

@@ -1019,7 +1019,7 @@ export function AIApplicationGeneration({ activePath }: AIApplicationGenerationP
<Card className="p-6">
<h4 className="mb-3"></h4>
<div className="p-8 bg-gray-50 rounded-lg">
<div className="p-8 bg-muted rounded-lg">
<div className="flex items-center justify-between">
<div className="text-center">
<div className="w-24 h-24 bg-blue-100 rounded-lg flex items-center justify-center mx-auto mb-2">

View File

@@ -1026,27 +1026,27 @@ export function AIAuditLog({ activePath }: AIAuditLogProps) {
<div>
<h4 className="mb-3"></h4>
<div className="grid grid-cols-3 gap-4">
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1">ID</div>
<div className="font-mono text-sm">{selectedLog.traceId}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedLog.decisionNo}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedLog.decisionType}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedLog.fieldName} ({selectedLog.fieldArea})</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedLog.cropType}</div>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="text-xs text-muted-foreground mb-1"></div>
<div className="font-medium">{selectedLog.userName}</div>
</div>
@@ -1110,7 +1110,7 @@ export function AIAuditLog({ activePath }: AIAuditLogProps) {
</div>
{step.details && (
<div className="p-3 bg-gray-50 rounded-lg mb-2">
<div className="p-3 bg-muted rounded-lg mb-2">
<div className="text-xs font-medium mb-2"></div>
{step.details.modelName && (
<div className="text-xs mb-1">
@@ -1183,7 +1183,7 @@ export function AIAuditLog({ activePath }: AIAuditLogProps) {
<div className="space-y-4">
<div>
<h4 className="mb-2"></h4>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<div className="grid grid-cols-2 gap-3 text-sm">
<div>: {selectedStep.stepName}</div>
<div>: {selectedStep.startTime}</div>

View File

@@ -710,10 +710,10 @@ export function AIDataCenter({ activePath }: AIDataCenterProps) {
</div>
</div>
</Card>
<Card className="p-4 bg-gray-50">
<Card className="p-4 bg-muted">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-gray-100 rounded-full flex items-center justify-center">
<WifiOff className="w-5 h-5 text-gray-600" />
<div className="w-10 h-10 bg-muted rounded-full flex items-center justify-center">
<WifiOff className="w-5 h-5 text-muted-foreground" />
</div>
<div>
<p className="text-xs text-muted-foreground">线</p>
@@ -985,7 +985,7 @@ export function AIDataCenter({ activePath }: AIDataCenterProps) {
<h4 className="text-sm font-medium mb-3"></h4>
<div className="space-y-2">
{uploadedFiles.map((file, index) => (
<div key={index} className="flex items-center justify-between p-2 bg-gray-50 rounded">
<div key={index} className="flex items-center justify-between p-2 bg-muted rounded">
<div className="flex items-center gap-2 flex-1">
<FileText className="w-4 h-4 text-blue-600" />
<div className="flex-1">
@@ -1086,7 +1086,7 @@ export function AIDataCenter({ activePath }: AIDataCenterProps) {
</div>
{/* API认证配置 */}
<Card className="p-4 bg-gray-50">
<Card className="p-4 bg-muted">
<h4 className="text-sm mb-3">API认证配置</h4>
<div className="space-y-3">
<div>
@@ -1666,28 +1666,28 @@ export function AIDataCenter({ activePath }: AIDataCenterProps) {
</h4>
<div className="space-y-3">
<div className="flex items-center justify-between p-3 bg-gray-50 rounded">
<div className="flex items-center justify-between p-3 bg-muted rounded">
<div>
<p className="text-sm font-medium"></p>
<p className="text-xs text-muted-foreground"></p>
</div>
<Switch defaultChecked />
</div>
<div className="flex items-center justify-between p-3 bg-gray-50 rounded">
<div className="flex items-center justify-between p-3 bg-muted rounded">
<div>
<p className="text-sm font-medium"></p>
<p className="text-xs text-muted-foreground"></p>
</div>
<Switch defaultChecked />
</div>
<div className="flex items-center justify-between p-3 bg-gray-50 rounded">
<div className="flex items-center justify-between p-3 bg-muted rounded">
<div>
<p className="text-sm font-medium"> (3σ)</p>
<p className="text-xs text-muted-foreground">3</p>
</div>
<Switch defaultChecked />
</div>
<div className="flex items-center justify-between p-3 bg-gray-50 rounded">
<div className="flex items-center justify-between p-3 bg-muted rounded">
<div>
<p className="text-sm font-medium"></p>
<p className="text-xs text-muted-foreground"></p>
@@ -2026,7 +2026,7 @@ export function AIDataCenter({ activePath }: AIDataCenterProps) {
</div>
{/* 协议配置信息 */}
<div className="mt-4 p-3 bg-gray-50 rounded-md">
<div className="mt-4 p-3 bg-muted rounded-md">
<h5 className="text-xs font-medium text-muted-foreground mb-2"></h5>
<div className="grid grid-cols-2 gap-3 text-xs">
{selectedDevice?.protocol === 'MQTT' && (
@@ -2064,7 +2064,7 @@ export function AIDataCenter({ activePath }: AIDataCenterProps) {
</h4>
{selectedDevice?.sensors && selectedDevice.sensors.length > 0 && (
<Card className="p-4 bg-gray-50">
<Card className="p-4 bg-muted">
<div className="grid grid-cols-4 gap-4">
<div>
<Label className="text-xs"></Label>
@@ -2307,7 +2307,7 @@ export function AIDataCenter({ activePath }: AIDataCenterProps) {
{ time: '2024-10-23 14:28:15', status: 'success', msg: '数据采集成功,所有传感器正常' },
{ time: '2024-10-23 14:27:45', status: 'success', msg: '数据采集成功,所有传感器正常' },
].map((log, idx) => (
<div key={idx} className="flex items-start gap-3 p-2 bg-gray-50 rounded text-xs">
<div key={idx} className="flex items-start gap-3 p-2 bg-muted rounded text-xs">
<Clock className="w-3 h-3 text-muted-foreground flex-shrink-0 mt-0.5" />
<div className="flex-1">
<div className="flex items-center gap-2">

View File

@@ -1356,7 +1356,7 @@ export function AIDecisionDetail({ activePath }: AIDecisionDetailProps) {
{expandedSections.has('snapshot') && (
<div className="space-y-3">
{autoDecisionDetail.dataSnapshot.map((data, idx) => (
<div key={idx} className="p-3 bg-gray-50 rounded">
<div key={idx} className="p-3 bg-muted rounded">
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2">
<Database className="w-4 h-4 text-blue-600" />
@@ -1566,7 +1566,7 @@ export function AIDecisionDetail({ activePath }: AIDecisionDetailProps) {
<div className="grid grid-cols-2 gap-4">
<div>
<div className="text-sm text-muted-foreground mb-2"></div>
<div className="p-3 bg-gray-50 rounded space-y-1 text-sm">
<div className="p-3 bg-muted rounded space-y-1 text-sm">
{Object.entries(autoDecisionDetail.finalDecision.parameters).map(([key, value]) => (
<div key={key}>
<span className="text-muted-foreground">{key}:</span>
@@ -1599,7 +1599,7 @@ export function AIDecisionDetail({ activePath }: AIDecisionDetailProps) {
<div className="text-sm text-muted-foreground mb-2"></div>
<div className="space-y-2">
{autoDecisionDetail.finalDecision.alternatives.map((alt, i) => (
<div key={i} className="p-3 bg-gray-50 rounded text-sm">
<div key={i} className="p-3 bg-muted rounded text-sm">
{alt}
</div>
))}
@@ -1786,7 +1786,7 @@ export function AIDecisionDetail({ activePath }: AIDecisionDetailProps) {
{manualDecisionDetail.manualInput.explanation && (
<div>
<div className="text-sm text-muted-foreground mb-2"></div>
<div className="p-4 bg-gray-50 rounded border">
<div className="p-4 bg-muted rounded border">
<p className="text-sm whitespace-pre-line">{manualDecisionDetail.manualInput.explanation}</p>
</div>
</div>

View File

@@ -675,7 +675,7 @@ export function AIDecisionGeneration({ activePath }: AIDecisionGenerationProps)
</div>
</TableCell>
<TableCell>
<code className="text-xs bg-gray-100 px-2 py-1 rounded">
<code className="text-xs bg-muted px-2 py-1 rounded">
{rule.condition.substring(0, 30)}...
</code>
</TableCell>
@@ -898,7 +898,7 @@ export function AIDecisionGeneration({ activePath }: AIDecisionGenerationProps)
</div>
<div className="divide-y">
{decisionRecords.map((record) => (
<div key={record.id} className="p-4 hover:bg-gray-50 transition-colors">
<div key={record.id} className="p-4 hover:bg-accent transition-colors">
<div className="flex items-start justify-between mb-3">
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
@@ -960,7 +960,7 @@ export function AIDecisionGeneration({ activePath }: AIDecisionGenerationProps)
<p className="text-sm">{record.finalDecision}</p>
</div>
<div className="p-3 bg-gray-50 rounded">
<div className="p-3 bg-muted rounded">
<p className="text-xs text-muted-foreground mb-1"></p>
<p className="text-xs">{record.reasoning}</p>
<div className="flex gap-2 mt-2">
@@ -1309,7 +1309,7 @@ export function AIDecisionGeneration({ activePath }: AIDecisionGenerationProps)
<div>
<Label></Label>
<div className="field-value bg-gray-50">
<div className="field-value">
{selectedDecision.reasoning}
</div>
</div>

View File

@@ -1001,7 +1001,7 @@ export function AIDecisionLog({ activePath }: AIDecisionLogProps) {
{filteredLogs.map((log) => (
<TableRow key={log.id}>
<TableCell>
<code className="text-xs bg-gray-100 px-2 py-1 rounded">{log.id}</code>
<code className="text-xs bg-muted px-2 py-1 rounded">{log.id}</code>
</TableCell>
<TableCell>
<div className="text-sm">{log.timestamp}</div>
@@ -1082,7 +1082,7 @@ export function AIDecisionLog({ activePath }: AIDecisionLogProps) {
<div className="grid grid-cols-4 gap-4 text-sm">
<div>
<div className="text-xs text-muted-foreground mb-1">ID</div>
<code className="text-xs bg-gray-100 px-2 py-1 rounded">{selectedLog.id}</code>
<code className="text-xs bg-muted px-2 py-1 rounded">{selectedLog.id}</code>
</div>
<div>
<div className="text-xs text-muted-foreground mb-1"></div>
@@ -1115,7 +1115,7 @@ export function AIDecisionLog({ activePath }: AIDecisionLogProps) {
<h4></h4>
</button>
{expandedSections.has('trigger') && (
<div className="p-4 bg-gray-50 rounded-lg space-y-2">
<div className="p-4 bg-muted rounded-lg space-y-2">
<div className="grid grid-cols-2 gap-4 text-sm">
<div>
<span className="text-muted-foreground"></span>
@@ -1157,7 +1157,7 @@ export function AIDecisionLog({ activePath }: AIDecisionLogProps) {
</Badge>
</button>
{expandedSections.has('input') && (
<div className="p-4 bg-gray-50 rounded-lg">
<div className="p-4 bg-muted rounded-lg">
<div className="grid grid-cols-3 gap-3 text-sm">
{Object.entries(selectedLog.inputData).map(([key, value]) => (
<div key={key} className="p-3 bg-white rounded border">

View File

@@ -838,7 +838,7 @@ export function AIDecisionSimulation({ activePath }: AIDecisionSimulationProps)
{simulationResults.map((result) => (
<TableRow key={result.id}>
<TableCell>
<code className="text-xs bg-gray-100 px-2 py-1 rounded">{result.id}</code>
<code className="text-xs bg-muted px-2 py-1 rounded">{result.id}</code>
</TableCell>
<TableCell>
<div className="font-medium">{result.scenarioName}</div>
@@ -1369,7 +1369,7 @@ export function AIDecisionSimulation({ activePath }: AIDecisionSimulationProps)
<span className="font-medium">{selectedResult.evaluation.practicality}</span>
</div>
</div>
<div className="p-3 bg-gray-50 rounded-lg mt-3">
<div className="p-3 bg-muted rounded-lg mt-3">
<div className="text-sm text-muted-foreground">{selectedResult.evaluation.feedback}</div>
</div>
</div>

View File

@@ -617,7 +617,7 @@ export function AIDecisionSupport({ activePath }: AIDecisionSupportProps) {
decision.decisionLevel === '紧急' ? 'border-l-red-500 bg-red-50/50' :
decision.decisionLevel === '重要' ? 'border-l-orange-500 bg-orange-50/50' :
decision.decisionLevel === '一般' ? 'border-l-blue-500 bg-blue-50/50' :
'border-l-gray-500 bg-gray-50/50'
'border-l-gray-500 bg-muted'
}`}>
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-2">
@@ -737,7 +737,7 @@ export function AIDecisionSupport({ activePath }: AIDecisionSupportProps) {
<Card className="p-4">
<h4 className="mb-4 flex items-center gap-2">
<BarChart3 className="w-4 h-4 text-purple-600" />
<EFBFBD><EFBFBD>
</h4>
<ResponsiveContainer width="100%" height={250}>
<BarChart data={executionRate} layout="vertical">
@@ -942,7 +942,7 @@ export function AIDecisionSupport({ activePath }: AIDecisionSupportProps) {
</h4>
<div className="space-y-4">
{selectedDecision.ruleLogic.map((rule, idx) => (
<Card key={idx} className={`p-4 ${rule.matched ? 'bg-green-50 border-green-200' : 'bg-gray-50'}`}>
<Card key={idx} className={`p-4 ${rule.matched ? 'bg-green-50 border-green-200' : 'bg-muted'}`}>
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-2">
<div className={`w-6 h-6 rounded-full flex items-center justify-center ${
@@ -1002,7 +1002,7 @@ export function AIDecisionSupport({ activePath }: AIDecisionSupportProps) {
<div className="mb-4">
<Label></Label>
<div className="field-value bg-gray-50">
<div className="field-value">
<p className="text-sm leading-relaxed">{selectedDecision.reasoning}</p>
</div>
</div>

View File

@@ -3,13 +3,13 @@ import { Card } from '../ui/card';
import { Button } from '../ui/button';
import { Input } from '../ui/input';
import { Label } from '../ui/label';
import { Textarea } from '../ui/textarea';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '../ui/dialog';
import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs';
import { Badge } from '../ui/badge';
import { UserProfile, PasswordChange } from '../../types/profile';
import { User, Mail, Phone, Building, Briefcase, Lock, Save, Shield } from 'lucide-react';
import { User, Mail, Phone, Building, Briefcase, Lock, Save, Shield, CheckCircle, XCircle, Clock } from 'lucide-react';
import { toast } from 'sonner@2.0.3';
export function PersonalInfo() {
@@ -30,6 +30,8 @@ export function PersonalInfo() {
roleNames: ['超级管理员'],
bio: '负责系统整体架构和技术管理',
address: '北京市海淀区中关村大街1号',
// 账户状态:'pending'待审核(企业名称可编辑)、'approved'审核通过(企业名称只读)、'rejected'驳回(企业名称只读)
status: 'approved', // 默认审核通过
createdAt: '2024-01-01T00:00:00',
lastLoginTime: '2024-10-14T09:30:00',
lastLoginIp: '192.168.1.100',
@@ -111,12 +113,51 @@ export function PersonalInfo() {
setHasChanges(true);
};
// 获取状态配置
const getStatusConfig = (status?: string) => {
switch (status) {
case 'pending':
return {
label: '待审核',
icon: Clock,
className: 'bg-yellow-100 text-yellow-800 border-yellow-200',
};
case 'approved':
return {
label: '审核通过',
icon: CheckCircle,
className: 'bg-green-100 text-green-800 border-green-200',
};
case 'rejected':
return {
label: '驳回',
icon: XCircle,
className: 'bg-red-100 text-red-800 border-red-200',
};
default:
return {
label: '待审核',
icon: Clock,
className: 'bg-gray-100 text-gray-800 border-gray-200',
};
}
};
const statusConfig = getStatusConfig(profile.status);
const StatusIcon = statusConfig.icon;
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h2 className="text-green-800"></h2>
<p className="text-muted-foreground"></p>
<div className="flex items-center gap-4">
<div>
<h2 className="text-green-800"></h2>
<p className="text-muted-foreground"></p>
</div>
<div className={`flex items-center gap-2 px-3 py-1 rounded-lg border ${statusConfig.className}`}>
<StatusIcon className="w-4 h-4" />
<span className="text-sm">{statusConfig.label}</span>
</div>
</div>
<div className="flex gap-2">
<Button variant="outline" onClick={() => setShowPasswordDialog(true)}>
@@ -231,23 +272,6 @@ export function PersonalInfo() {
onChange={(e) => updateProfile({ birthday: e.target.value })}
/>
</div>
<div className="md:col-span-2">
<Label></Label>
<Textarea
value={profile.bio}
onChange={(e) => updateProfile({ bio: e.target.value })}
placeholder="介绍一下自己"
rows={3}
/>
</div>
<div className="md:col-span-2">
<Label></Label>
<Input
value={profile.address}
onChange={(e) => updateProfile({ address: e.target.value })}
placeholder="请输入地址"
/>
</div>
</div>
</div>
</Card>
@@ -263,36 +287,39 @@ export function PersonalInfo() {
<Building className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted-foreground" />
<Input
value={profile.enterpriseName}
disabled
className="pl-10 bg-gray-50"
onChange={(e) => updateProfile({ enterpriseName: e.target.value })}
disabled={profile.status === 'approved'}
className={`pl-10 ${profile.status === 'approved' ? 'bg-muted' : ''}`}
placeholder={profile.status !== 'approved' ? '请输入企业名称' : ''}
/>
</div>
{profile.status === 'pending' ? (
<p className="text-xs text-yellow-600 dark:text-yellow-500 mt-1"></p>
) : profile.status === 'rejected' ? (
<p className="text-xs text-red-600 dark:text-red-500 mt-1"></p>
) : (
<p className="text-xs text-muted-foreground mt-1"></p>
)}
</div>
<div>
<Label></Label>
<Input
value={profile.department}
onChange={(e) => updateProfile({ department: e.target.value })}
placeholder="请输入部门"
disabled
className="bg-muted"
/>
<p className="text-xs text-muted-foreground mt-1"></p>
</div>
<div>
<Label></Label>
<Input
value={profile.position}
onChange={(e) => updateProfile({ position: e.target.value })}
placeholder="请输入职位"
/>
</div>
<div>
<div className="md:col-span-2">
<Label></Label>
<div className="flex flex-wrap gap-2 pt-2">
<div className="flex flex-wrap gap-2 mt-2">
{profile.roleNames.map((role, index) => (
<div key={index} className="px-3 py-1 bg-green-100 text-green-700 rounded-full text-sm">
<Badge key={index} variant="outline" className="px-3 py-1 bg-green-100 text-green-700 border-green-300 dark:bg-green-900/30 dark:text-green-400 dark:border-green-700">
{role}
</div>
</Badge>
))}
</div>
<p className="text-xs text-muted-foreground mt-1"></p>
</div>
</div>
</Card>
@@ -405,14 +432,16 @@ export function PersonalInfo() {
</Dialog>
{/* 使用说明 */}
<Card className="p-4 bg-blue-50 border-blue-200">
<h4 className="text-blue-900 mb-2">
<Card className="p-4 bg-blue-50 dark:bg-blue-950/30 border-blue-200 dark:border-blue-900">
<h4 className="text-blue-900 dark:text-blue-400 mb-2">
<User className="w-4 h-4 inline mr-2" />
</h4>
<ul className="space-y-1 text-sm text-blue-800">
<ul className="space-y-1 text-sm text-blue-800 dark:text-blue-300">
<li> "保存修改"</li>
<li> </li>
<li> </li>
<li> </li>
<li> 使</li>
<li> </li>
<li> </li>
<li> </li>

View File

@@ -770,7 +770,7 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
{/* 筛选结果提示 */}
{(filterField !== 'all' || filterCrop !== 'all' || filterExecutor !== 'all' || filterType !== 'all' || filterStatus !== 'all') && (
<div className="flex items-center gap-2 text-sm">
<Badge variant="outline" className="bg-green-50">
<Badge variant="outline">
: {filteredTasks.length}
</Badge>
{filterField !== 'all' && (
@@ -847,7 +847,7 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
{/* 日历网格 */}
<div className="border rounded-lg overflow-hidden">
{/* 星期标题 */}
<div className="grid grid-cols-7 bg-gray-100">
<div className="grid grid-cols-7 bg-muted">
{weekDays.map(day => (
<div key={day} className="p-3 text-center text-sm font-medium border-r last:border-r-0">
{day}
@@ -869,7 +869,7 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
<div
key={index}
className={`min-h-[120px] p-2 border-r border-b last:border-r-0 ${
!isCurrentMonth ? 'bg-gray-50' : 'bg-white'
!isCurrentMonth ? 'bg-muted' : 'bg-card'
} ${isToday ? 'ring-2 ring-green-500' : ''}`}
onDrop={(e) => handleDrop(day, e)}
onDragOver={handleDragOver}
@@ -907,10 +907,10 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
</Card>
{/* 说明 */}
<Card className="p-4 bg-blue-50 border-blue-200">
<Card className="p-4">
<div className="flex items-start gap-2">
<Zap className="w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-blue-900">
<div className="text-sm">
<p className="mb-2"> {filteredTasks.length} </p>
<ul className="space-y-1 text-xs">
<li> <strong></strong>: </li>
@@ -1022,10 +1022,10 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
</Card>
{/* 甘特图说明 */}
<Card className="p-4 bg-green-50 border-green-200">
<Card className="p-4">
<div className="flex items-start gap-2">
<BarChart3 className="w-5 h-5 text-green-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-green-900">
<div className="text-sm">
<p className="mb-2"> {filteredTasks.length} </p>
<ul className="space-y-1 text-xs">
<li> <strong></strong>: </li>
@@ -1055,7 +1055,7 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
<Card key={field.id} className="p-6">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
<div className="p-3 bg-green-100 rounded-lg">
<div className="p-3 bg-green-50 rounded-lg">
<MapPin className="w-6 h-6 text-green-600" />
</div>
<div>
@@ -1088,7 +1088,7 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
: 0}%
</span>
</div>
<div className="h-3 bg-gray-200 rounded-full overflow-hidden flex">
<div className="h-3 bg-muted rounded-full overflow-hidden flex">
<div
className="bg-blue-500 transition-all"
style={{
@@ -1141,7 +1141,7 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
<span className="text-muted-foreground"></span>
<span className="font-medium">{task.progress}%</span>
</div>
<div className="h-2 bg-gray-200 rounded-full overflow-hidden">
<div className="h-2 bg-muted rounded-full overflow-hidden">
<div
className="h-full transition-all"
style={{
@@ -1166,10 +1166,10 @@ export function OperationCalendar({ activePath }: OperationCalendarProps) {
</div>
{/* 进度说明 */}
<Card className="p-4 bg-purple-50 border-purple-200">
<Card className="p-4">
<div className="flex items-start gap-2">
<TrendingUp className="w-5 h-5 text-purple-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-purple-900">
<div className="text-sm">
<p className="mb-2"></p>
<ul className="space-y-1 text-xs">
<li> <strong></strong>: 🔵 -🟢 绿- -</li>

View File

@@ -1920,7 +1920,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
{/* 甘特图 */}
{plan.activities.length > 0 && (
<div className="p-4 bg-gray-50 rounded-lg">
<div className="p-4 bg-muted rounded-lg">
<h4 className="mb-3 flex items-center gap-2">
<Activity className="w-4 h-4 text-blue-600" />
@@ -1939,7 +1939,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
{activity.startDate} ~ {activity.endDate} ({activity.duration})
</span>
</div>
<div className="relative h-8 bg-white rounded border">
<div className="relative h-8 bg-background rounded border">
<div
className="absolute h-full rounded flex items-center px-2 text-xs text-white"
style={{
@@ -2545,7 +2545,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
{/* 甘特图可视化 */}
{editingActivities.length > 0 && editingActivities[0].startDate && (
<Card className="p-6 bg-gray-50">
<Card className="p-6 bg-muted">
{/* 月份选择器 */}
<div className="flex items-center justify-between mb-4">
<div>
@@ -2566,7 +2566,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
>
<ChevronRight className="w-4 h-4 rotate-180" />
</Button>
<div className="px-4 py-1 bg-white rounded border min-w-[120px] text-center">
<div className="px-4 py-1 bg-background rounded border min-w-[120px] text-center">
<span className="text-sm font-medium">
{selectedMonth.getFullYear()}{selectedMonth.getMonth() + 1}
</span>
@@ -2590,7 +2590,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
</div>
{/* 日期刻度 */}
<div className={`mb-2 relative h-8 bg-white rounded border overflow-hidden transition-all ${
<div className={`mb-2 relative h-8 bg-background rounded border overflow-hidden transition-all ${
isTimelineDragging ? 'ring-2 ring-blue-500 shadow-lg' : ''
}`}>
<div className="flex h-full">
@@ -2604,12 +2604,8 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
<div
key={index}
className={`flex-1 border-r last:border-r-0 flex items-center justify-center text-xs transition-colors ${
isToday ? 'bg-blue-100' : ''
isToday ? 'bg-blue-100' : (date.getDay() === 0 || date.getDay() === 6 ? 'bg-muted' : '')
}`}
style={{
backgroundColor: isToday ? '#dbeafe' :
(date.getDay() === 0 || date.getDay() === 6 ? '#f9fafb' : '#fff'),
}}
>
<div className="text-center">
<div className={`${isToday ? 'text-blue-600 font-bold' : 'text-muted-foreground'}`}>
@@ -2635,7 +2631,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
{/* 甘特图活动条 */}
<div
ref={ganttRef}
className="space-y-3 select-none relative"
className="space-y-3 select-none relative p-4 rounded-lg bg-card"
onMouseDown={handleTimelineDragStart}
onMouseMove={(e) => {
handleTimelineDragMove(e);
@@ -2689,7 +2685,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
{activity.startDate} ~ {activity.endDate} ({activity.duration})
</span>
</div>
<div className="relative h-10 bg-white rounded border">
<div className="relative h-10 bg-background rounded border">
<div
className="gantt-activity-bar absolute h-full rounded flex items-center px-2 text-xs text-white transition-all group"
style={{
@@ -2820,7 +2816,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
</Button>
</div>
<div className="p-3 bg-gray-50 rounded-lg">
<div className="p-3 bg-muted rounded-lg">
<p className="text-xs text-muted-foreground mb-2"></p>
<div className="flex flex-wrap gap-2">
{template.activities.map(act => (
@@ -2858,7 +2854,7 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
</DialogHeader>
{selectedWorkOrder && (
<div className="space-y-4">
<div className="p-4 bg-gray-50 rounded-lg">
<div className="p-4 bg-muted rounded-lg">
<div className="grid grid-cols-2 gap-4">
<div>
<p className="text-xs text-muted-foreground"></p>
@@ -3090,11 +3086,11 @@ export function OperationPlanning({ activePath }: OperationPlanningProps) {
</h4>
<div className="grid grid-cols-2 gap-4">
<div className="p-4 bg-gray-50 rounded-lg">
<div className="p-4 bg-muted rounded-lg">
<p className="text-xs text-muted-foreground"></p>
<p className="text-sm font-medium mt-1">{selectedPlan.createdBy}</p>
</div>
<div className="p-4 bg-gray-50 rounded-lg">
<div className="p-4 bg-muted rounded-lg">
<p className="text-xs text-muted-foreground"></p>
<p className="text-sm font-medium mt-1">{selectedPlan.createdAt}</p>
</div>