feat(iit): V3.2 data consistency + project isolation + admin config redesign + Chinese labels
Summary: - Refactor timeline API to read from qc_field_status (SSOT) instead of qc_logs - Add field-issues paginated API with severity/dimension/recordId filters - Add LEFT JOIN field_metadata + qc_event_status for Chinese display names - Implement per-project ChatOrchestrator cache and SessionMemory isolation - Redesign admin IIT config tabs (REDCap -> Fields -> KB -> Rules -> Members) - Add AI-powered QC rule generation (D3 programmatic + D1/D5/D6 LLM-based) - Add clickable warning/critical detail Modal in ReportsPage - Auto-dispatch eQuery after batch QC via DailyQcOrchestrator - Update module status documentation to v3.2 Backend changes: - iitQcCockpitController: rewrite getTimeline from qc_field_status, add getFieldIssues - iitQcCockpitRoutes: add field-issues route - ChatOrchestrator: per-projectId cached instances - SessionMemory: keyed by userId::projectId - WechatCallbackController: resolve projectId from iitUserMapping - iitRuleSuggestionService: dimension-based suggest + generateD3Rules - iitBatchController: call DailyQcOrchestrator after batch QC Frontend changes: - AiStreamPage: adapt to new timeline structure with dimension tags - ReportsPage: clickable stats cards with issue detail Modal - IitProjectDetailPage: reorder tabs, add AI rule generation UI - iitProjectApi: add TimelineIssue, FieldIssueItem types and APIs Status: TypeScript compilation verified, no new lint errors Made-with: Cursor
This commit is contained in:
@@ -73,9 +73,6 @@ const ModulePermissionModal: React.FC<ModulePermissionModalProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
// 可用模块(租户已订阅的)
|
||||
const subscribedModules = moduleOptions.filter((m) => m.isSubscribed);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={`配置模块权限 - ${membership.tenantName}`}
|
||||
@@ -88,28 +85,35 @@ const ModulePermissionModal: React.FC<ModulePermissionModalProps> = ({
|
||||
<Spin spinning={loading}>
|
||||
<Alert
|
||||
message="模块权限说明"
|
||||
description="选择用户在该租户内可以访问的模块。取消所有选择将默认继承租户的全部模块权限。"
|
||||
description="选择用户在该租户内可以访问的模块。取消所有选择将默认继承租户的全部模块权限。灰色模块表示租户尚未订阅。"
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
|
||||
{subscribedModules.length > 0 ? (
|
||||
{moduleOptions.length > 0 ? (
|
||||
<Checkbox.Group
|
||||
value={selectedModules}
|
||||
onChange={(values) => setSelectedModules(values as string[])}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Row gutter={[16, 16]}>
|
||||
{subscribedModules.map((module) => (
|
||||
{moduleOptions.map((module) => (
|
||||
<Col span={12} key={module.code}>
|
||||
<Checkbox value={module.code}>{module.name}</Checkbox>
|
||||
<Checkbox value={module.code}>
|
||||
{module.name}
|
||||
{!module.isSubscribed && (
|
||||
<Text type="secondary" style={{ fontSize: 12, marginLeft: 4 }}>
|
||||
(未订阅)
|
||||
</Text>
|
||||
)}
|
||||
</Checkbox>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</Checkbox.Group>
|
||||
) : (
|
||||
<Text type="secondary">该租户暂无可用模块</Text>
|
||||
<Text type="secondary">暂无可用模块</Text>
|
||||
)}
|
||||
</Spin>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user