diff --git a/server/src/app/api/v1/endpoints/agent_assets.py b/server/src/app/api/v1/endpoints/agent_assets.py index 9d7cb9b..ee376a0 100644 --- a/server/src/app/api/v1/endpoints/agent_assets.py +++ b/server/src/app/api/v1/endpoints/agent_assets.py @@ -636,7 +636,7 @@ def list_agent_asset_versions( response_model=AgentAssetVersionRead, status_code=status.HTTP_201_CREATED, summary="创建资产版本", - description="为指定资产创建新版本;规则使用 Markdown,其他资产使用 JSON 快照。", + description="为指定资产创建新版本;规则和任务源文件可使用 Markdown,技能与 MCP 使用 JSON 快照。", responses={ status.HTTP_400_BAD_REQUEST: { "model": ErrorResponse, diff --git a/server/src/app/services/agent_assets.py b/server/src/app/services/agent_assets.py index f28e9f7..fd17494 100644 --- a/server/src/app/services/agent_assets.py +++ b/server/src/app/services/agent_assets.py @@ -501,10 +501,10 @@ class AgentAssetService( ): raise ValueError("规则资产版本内容必须使用 markdown。") if ( - asset.asset_type != AgentAssetType.RULE.value + asset.asset_type not in {AgentAssetType.RULE.value, AgentAssetType.TASK.value} and payload.content_type != AgentAssetContentType.JSON ): - raise ValueError("技能、MCP、任务资产版本内容必须使用 json。") + raise ValueError("技能、MCP 资产版本内容必须使用 json。") if payload.content_type == AgentAssetContentType.MARKDOWN and not isinstance( payload.content, str ): diff --git a/server/src/app/services/agent_foundation_asset_seed.py b/server/src/app/services/agent_foundation_asset_seed.py index 70b8dda..54eedc8 100644 --- a/server/src/app/services/agent_foundation_asset_seed.py +++ b/server/src/app/services/agent_foundation_asset_seed.py @@ -27,12 +27,40 @@ from app.services.agent_foundation_constants import ( COMPANY_COMMUNICATION_RULE_VERSION, COMPANY_TRAVEL_RULE_SCENARIO_JSON, COMPANY_TRAVEL_RULE_VERSION, + DIGITAL_EMPLOYEE_SKILL_CATEGORIES, + DIGITAL_EMPLOYEE_TASK_CATEGORY_MAP, ) logger = get_logger("app.services.agent_foundation") class AgentFoundationAssetSeedMixin: + def _digital_employee_task_config(self, code: str, cron: str) -> dict[str, object]: + return { + "cron": cron, + "agent": AgentName.HERMES.value, + "skill_category": DIGITAL_EMPLOYEE_TASK_CATEGORY_MAP.get(code, "整理"), + "skill_category_options": list(DIGITAL_EMPLOYEE_SKILL_CATEGORIES), + } + + def _digital_employee_task_content( + self, + code: str, + task_type: str, + schedule: str, + **extra: object, + ) -> str: + return self._json_content( + { + "task_type": task_type, + "skill_category": DIGITAL_EMPLOYEE_TASK_CATEGORY_MAP.get(code, "整理"), + "skill_category_options": list(DIGITAL_EMPLOYEE_SKILL_CATEGORIES), + "schedule": schedule, + "target_agent": AgentName.HERMES.value, + **extra, + } + ) + def _seed_agent_assets(self) -> None: existing_codes = set(self.db.scalars(select(AgentAsset.code)).all()) @@ -239,7 +267,7 @@ class AgentFoundationAssetSeedMixin: current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", - config_json={"cron": "0 9 * * *", "agent": AgentName.HERMES.value}, + config_json=self._digital_employee_task_config("task.hermes.daily_risk_scan", "0 9 * * *"), ) ar_summary_task = AgentAsset( @@ -255,7 +283,7 @@ class AgentFoundationAssetSeedMixin: current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", - config_json={"cron": "0 10 * * 1", "agent": AgentName.HERMES.value}, + config_json=self._digital_employee_task_config("task.hermes.weekly_ar_summary", "0 10 * * 1"), ) rule_digest_task = AgentAsset( @@ -271,7 +299,7 @@ class AgentFoundationAssetSeedMixin: current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", - config_json={"cron": "0 18 * * *", "agent": AgentName.HERMES.value}, + config_json=self._digital_employee_task_config("task.hermes.rule_review_digest", "0 18 * * *"), ) knowledge_index_task = AgentAsset( @@ -287,7 +315,7 @@ class AgentFoundationAssetSeedMixin: current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", - config_json={"cron": "0 0 * * *", "agent": AgentName.HERMES.value}, + config_json=self._digital_employee_task_config("task.hermes.knowledge_index_sync", "0 0 * * *"), ) self.db.add_all( @@ -467,12 +495,10 @@ class AgentFoundationAssetSeedMixin: AgentAssetVersion( asset=task_asset, version="v1.0.0", - content=self._json_content( - { - "task_type": "daily_risk_scan", - "schedule": "0 9 * * *", - "target_agent": AgentName.HERMES.value, - } + content=self._digital_employee_task_content( + "task.hermes.daily_risk_scan", + "daily_risk_scan", + "0 9 * * *", ), content_type=AgentAssetContentType.JSON.value, change_note="初始化任务快照。", @@ -481,12 +507,10 @@ class AgentFoundationAssetSeedMixin: AgentAssetVersion( asset=ar_summary_task, version="v1.0.0", - content=self._json_content( - { - "task_type": "weekly_ar_summary", - "schedule": "0 10 * * 1", - "target_agent": AgentName.HERMES.value, - } + content=self._digital_employee_task_content( + "task.hermes.weekly_ar_summary", + "weekly_ar_summary", + "0 10 * * 1", ), content_type=AgentAssetContentType.JSON.value, change_note="初始化应收账龄汇总任务。", @@ -495,12 +519,10 @@ class AgentFoundationAssetSeedMixin: AgentAssetVersion( asset=rule_digest_task, version="v1.0.0", - content=self._json_content( - { - "task_type": "rule_review_digest", - "schedule": "0 18 * * *", - "target_agent": AgentName.HERMES.value, - } + content=self._digital_employee_task_content( + "task.hermes.rule_review_digest", + "rule_review_digest", + "0 18 * * *", ), content_type=AgentAssetContentType.JSON.value, change_note="初始化规则待审摘要任务。", @@ -509,15 +531,13 @@ class AgentFoundationAssetSeedMixin: AgentAssetVersion( asset=knowledge_index_task, version="v1.0.0", - content=self._json_content( - { - "task_type": "knowledge_index_sync", - "schedule": "0 0 * * *", - "target_agent": AgentName.HERMES.value, - "folder": "报销制度", - "changed_only": True, - "index_engine": "lightrag", - } + content=self._digital_employee_task_content( + "task.hermes.knowledge_index_sync", + "knowledge_index_sync", + "0 0 * * *", + folder="报销制度", + changed_only=True, + index_engine="lightrag", ), content_type=AgentAssetContentType.JSON.value, change_note="初始化制度知识与规则草稿形成任务。", diff --git a/server/src/app/services/agent_foundation_asset_topup.py b/server/src/app/services/agent_foundation_asset_topup.py index 711b490..d0e0bcd 100644 --- a/server/src/app/services/agent_foundation_asset_topup.py +++ b/server/src/app/services/agent_foundation_asset_topup.py @@ -9,7 +9,6 @@ from app.core.agent_enums import ( AgentAssetDomain, AgentAssetStatus, AgentAssetType, - AgentName, AgentReviewStatus, ) from app.core.logging import get_logger @@ -27,17 +26,46 @@ from app.services.agent_foundation_constants import ( COMPANY_COMMUNICATION_RULE_VERSION, COMPANY_TRAVEL_RULE_SCENARIO_JSON, COMPANY_TRAVEL_RULE_VERSION, + DIGITAL_EMPLOYEE_SKILL_CATEGORIES, + DIGITAL_EMPLOYEE_TASK_CATEGORY_MAP, ) logger = get_logger("app.services.agent_foundation") class AgentFoundationAssetTopUpMixin: + def _sync_digital_employee_skill_categories(self) -> None: + category_options = list(DIGITAL_EMPLOYEE_SKILL_CATEGORIES) + has_changes = False + + for code, category in DIGITAL_EMPLOYEE_TASK_CATEGORY_MAP.items(): + asset = self.db.scalar(select(AgentAsset).where(AgentAsset.code == code)) + if asset is None: + continue + + config_json = dict(asset.config_json or {}) + changed = False + if config_json.get("skill_category") != category: + config_json["skill_category"] = category + changed = True + if config_json.get("skill_category_options") != category_options: + config_json["skill_category_options"] = category_options + changed = True + + if changed: + asset.config_json = config_json + self.db.add(asset) + has_changes = True + + if has_changes: + self.db.commit() + def _top_up_agent_assets(self, existing_codes: set[str]) -> None: self._remove_legacy_rule_assets() existing_codes = set(self.db.scalars(select(AgentAsset.code)).all()) + self._sync_digital_employee_skill_categories() attachment_rule = self.db.scalar( select(AgentAsset).where(AgentAsset.code == ATTACHMENT_RULE_ASSET_CODE) @@ -557,18 +585,16 @@ class AgentFoundationAssetTopUpMixin: reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", - config_json={"cron": "0 10 * * 1", "agent": AgentName.HERMES.value}, + config_json=self._digital_employee_task_config("task.hermes.weekly_ar_summary", "0 10 * * 1"), ) self._ensure_asset_version( asset, version="v1.0.0", - content=self._json_content( - { - "task_type": "weekly_ar_summary", - "schedule": "0 10 * * 1", - "target_agent": AgentName.HERMES.value, - } + content=self._digital_employee_task_content( + "task.hermes.weekly_ar_summary", + "weekly_ar_summary", + "0 10 * * 1", ), content_type=AgentAssetContentType.JSON.value, change_note="初始化应收账龄汇总任务。", @@ -588,18 +614,16 @@ class AgentFoundationAssetTopUpMixin: reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", - config_json={"cron": "0 18 * * *", "agent": AgentName.HERMES.value}, + config_json=self._digital_employee_task_config("task.hermes.rule_review_digest", "0 18 * * *"), ) self._ensure_asset_version( asset, version="v1.0.0", - content=self._json_content( - { - "task_type": "rule_review_digest", - "schedule": "0 18 * * *", - "target_agent": AgentName.HERMES.value, - } + content=self._digital_employee_task_content( + "task.hermes.rule_review_digest", + "rule_review_digest", + "0 18 * * *", ), content_type=AgentAssetContentType.JSON.value, change_note="初始化规则待审摘要任务。", @@ -619,20 +643,18 @@ class AgentFoundationAssetTopUpMixin: reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", - config_json={"cron": "0 0 * * *", "agent": AgentName.HERMES.value}, + config_json=self._digital_employee_task_config("task.hermes.knowledge_index_sync", "0 0 * * *"), ) self._ensure_asset_version( asset, version="v1.0.0", - content=self._json_content( - { - "task_type": "knowledge_index_sync", - "schedule": "0 0 * * *", - "target_agent": AgentName.HERMES.value, - "folder": "报销制度", - "changed_only": True, - } + content=self._digital_employee_task_content( + "task.hermes.knowledge_index_sync", + "knowledge_index_sync", + "0 0 * * *", + folder="报销制度", + changed_only=True, ), content_type=AgentAssetContentType.JSON.value, change_note="初始化制度知识与规则草稿形成任务。", diff --git a/server/src/app/services/agent_foundation_constants.py b/server/src/app/services/agent_foundation_constants.py index 706fbef..8e75866 100644 --- a/server/src/app/services/agent_foundation_constants.py +++ b/server/src/app/services/agent_foundation_constants.py @@ -86,6 +86,22 @@ COMPANY_TRAVEL_RULE_SCENARIO_JSON = ("差旅费",) COMPANY_COMMUNICATION_RULE_SCENARIO_JSON = ("通信费",) +DIGITAL_EMPLOYEE_SKILL_CATEGORIES = ("积累", "升级", "整理", "评估") + +DIGITAL_EMPLOYEE_TASK_CATEGORY_MAP = { + + "task.hermes.daily_risk_scan": "评估", + + "task.hermes.weekly_ar_summary": "整理", + + "task.hermes.rule_review_digest": "升级", + + "task.hermes.knowledge_index_sync": "积累", + + "task.hermes.llm_wiki_rule_formation": "积累", + +} + ATTACHMENT_RULE_RUNTIME_CONFIG = { "kind": "policy_rule_draft", diff --git a/web/UI/首页新.png b/web/UI/首页新.png new file mode 100644 index 0000000..ca2e8a4 Binary files /dev/null and b/web/UI/首页新.png differ diff --git a/web/src/assets/homepage_backgraound.png b/web/src/assets/homepage_backgraound.png new file mode 100644 index 0000000..230b0f4 Binary files /dev/null and b/web/src/assets/homepage_backgraound.png differ diff --git a/web/src/assets/styles/app.css b/web/src/assets/styles/app.css index 35c8501..4635684 100644 --- a/web/src/assets/styles/app.css +++ b/web/src/assets/styles/app.css @@ -135,6 +135,7 @@ .main.archive-main, .main.policies-main, .main.audit-main, +.main.digital-employees-main, .main.logs-main, .main.employees-main, .main.settings-main { @@ -151,10 +152,12 @@ .workarea { min-height: 0; overflow: auto; padding: 24px; } .workarea.requests-workarea, .workarea.documents-workarea, +.workarea.workbench-workarea, .workarea.approval-workarea, .workarea.archive-workarea, .workarea.policies-workarea, .workarea.audit-workarea, +.workarea.digital-employees-workarea, .workarea.logs-workarea, .workarea.employees-workarea, .workarea.settings-workarea { @@ -162,6 +165,10 @@ overflow: hidden; padding: 20px 24px; } +.workarea.workbench-workarea { + overflow: hidden; + padding: 12px 14px 14px; +} .workarea.settings-workarea { padding: 0; background: #fff; @@ -195,6 +202,7 @@ } .workarea { padding: 18px 16px 28px; } + .workarea.workbench-workarea { overflow: auto; padding: 14px; } } @media (prefers-reduced-motion: reduce) { diff --git a/web/src/assets/styles/components/digital-employee-schedule-dialog.css b/web/src/assets/styles/components/digital-employee-schedule-dialog.css new file mode 100644 index 0000000..7852e99 --- /dev/null +++ b/web/src/assets/styles/components/digital-employee-schedule-dialog.css @@ -0,0 +1,166 @@ +.digital-schedule-overlay { + position: fixed; + inset: 0; + z-index: 1200; + display: flex; + align-items: flex-end; + justify-content: flex-end; + padding: 32px; + background: rgba(15, 23, 42, 0.28); +} + +.digital-schedule-dialog { + width: min(520px, calc(100vw - 64px)); + border-radius: 8px; + background: #fff; + box-shadow: 0 24px 80px rgba(15, 23, 42, 0.22); + overflow: hidden; +} + +.digital-schedule-head, +.digital-schedule-actions { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 18px 20px; + border-bottom: 1px solid #e2e8f0; +} + +.digital-schedule-head h3 { + margin: 4px 0 0; + color: #0f172a; + font-size: 18px; + font-weight: 820; +} + +.digital-schedule-kicker { + color: #64748b; + font-size: 12px; + font-weight: 760; +} + +.digital-schedule-close { + width: 32px; + height: 32px; + display: grid; + place-items: center; + border: 1px solid #dbe4ee; + border-radius: 6px; + background: #fff; + color: #475569; + cursor: pointer; +} + +.digital-schedule-body { + padding: 18px 20px 20px; +} + +.digital-schedule-mode-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 8px; +} + +.digital-schedule-mode { + min-height: 36px; + border: 1px solid #dbe4ee; + border-radius: 6px; + background: #fff; + color: #475569; + font-size: 13px; + font-weight: 760; + cursor: pointer; +} + +.digital-schedule-mode.active { + border-color: rgba(var(--theme-primary-rgb), 0.42); + background: var(--theme-primary-soft); + color: var(--theme-primary-active); +} + +.digital-schedule-fields { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; + margin-top: 16px; +} + +.digital-schedule-fields label { + display: grid; + gap: 6px; + color: #334155; + font-size: 13px; + font-weight: 760; +} + +.digital-schedule-fields input, +.digital-schedule-fields select { + width: 100%; + min-height: 38px; + border: 1px solid #dbe4ee; + border-radius: 6px; + padding: 0 10px; + color: #0f172a; + font: inherit; + background: #fff; +} + +.digital-schedule-cron-field { + grid-column: 1 / -1; +} + +.digital-schedule-preview { + margin: 16px 0 0; + padding: 10px 12px; + border-radius: 6px; + background: #f8fafc; + color: #475569; + font-size: 13px; + font-weight: 700; +} + +.digital-schedule-error { + margin: 10px 0 0; + color: #b91c1c; + font-size: 13px; + font-weight: 760; +} + +.digital-schedule-actions { + justify-content: flex-end; + border-top: 1px solid #e2e8f0; + border-bottom: 0; +} + +.digital-schedule-actions .success-action { + border-color: var(--success-line); + background: var(--success-soft); + color: var(--success-hover); +} + +.digital-schedule-dialog-enter-active, +.digital-schedule-dialog-leave-active { + transition: opacity 160ms ease; +} + +.digital-schedule-dialog-enter-from, +.digital-schedule-dialog-leave-to { + opacity: 0; +} + +@media (max-width: 720px) { + .digital-schedule-overlay { + align-items: flex-end; + padding: 16px; + } + + .digital-schedule-dialog { + width: 100%; + } + + .digital-schedule-mode-grid, + .digital-schedule-fields { + grid-template-columns: 1fr; + } +} diff --git a/web/src/assets/styles/components/personal-workbench-insights.css b/web/src/assets/styles/components/personal-workbench-insights.css new file mode 100644 index 0000000..bd87e19 --- /dev/null +++ b/web/src/assets/styles/components/personal-workbench-insights.css @@ -0,0 +1,135 @@ +.side-column { + display: grid; + grid-template-rows: minmax(0, 0.94fr) minmax(0, 1fr); + gap: 14px; + min-height: 0; + height: 100%; +} + +.side-panel { + padding: 10px 12px; + gap: 6px; +} + +.side-panel .section-head { + min-height: 24px; + margin-bottom: 0; +} + +.side-panel .section-head h2 { + font-size: 15px; +} + +.side-card-head { + align-items: center; +} + +.detail-action { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 4px; + min-height: 24px; + padding: 0; + border: 0; + background: transparent; + color: var(--workbench-muted); + font-size: 13px; + font-weight: 800; + white-space: nowrap; +} + +.detail-action:hover { + color: var(--workbench-primary-active); +} + +.detail-action i { + font-size: 16px; +} + +.expense-stats-panel, +.usage-profile-panel { + min-height: 0; + display: grid; + grid-template-rows: auto minmax(0, 1fr); +} + +.insight-metric-list, +.insight-profile-list { + min-height: 0; + display: grid; + grid-auto-rows: minmax(0, 1fr); + overflow: hidden; +} + +.insight-metric-row, +.insight-profile-card { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + align-items: center; + gap: 10px; + min-height: 0; + padding: 6px 0; + border-top: 1px solid var(--workbench-line-soft); +} + +.insight-metric-row:first-child, +.insight-profile-card:first-child { + border-top: 0; +} + +.insight-metric-label, +.insight-profile-label { + min-width: 0; + overflow: hidden; + color: var(--workbench-muted); + font-size: 12px; + font-weight: 650; + line-height: 1.2; + text-overflow: ellipsis; + white-space: nowrap; +} + +.insight-metric-value, +.insight-profile-value { + min-width: 0; + overflow: hidden; + color: var(--workbench-ink); + font-size: 14px; + font-weight: 850; + line-height: 1.15; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + font-variant-numeric: tabular-nums; +} + +.insight-metric-value small, +.insight-profile-value small { + margin-left: 2px; + color: var(--workbench-muted); + font-size: 11px; + font-weight: 700; +} + +.insight-metric-row--amount .insight-metric-value { + color: var(--workbench-primary-active); +} + +.insight-metric-row--warning .insight-metric-value { + color: var(--warning); +} + +.insight-metric-row--info .insight-metric-value { + color: var(--workbench-chart-blue); +} + +.insight-profile-icon, +.insight-profile-hint { + display: none; +} + +.insight-profile-copy { + min-width: 0; + display: contents; +} diff --git a/web/src/assets/styles/components/personal-workbench-responsive.css b/web/src/assets/styles/components/personal-workbench-responsive.css new file mode 100644 index 0000000..6936af0 --- /dev/null +++ b/web/src/assets/styles/components/personal-workbench-responsive.css @@ -0,0 +1,198 @@ +/* 1080p / 小高度屏:进一步压缩 AI 助手卡片高度 */ +@media (max-height: 980px) { + .workbench { + --hero-padding-top: 20px; + --hero-padding-bottom: 12px; + --hero-title-size: 28px; + --hero-copy-gap: 5px; + --composer-min-height: 108px; + --composer-textarea-height: 48px; + --composer-padding-block: 10px; + --quick-prompts-gap-top: 8px; + --capability-row-height: 96px; + gap: 9px; + } + + .assistant-hero { + --assistant-art-width: min(560px, 42vw); + padding: var(--hero-padding-top) 18px var(--hero-padding-bottom) 44px; + } + + .assistant-copy p { + font-size: 14px; + line-height: 1.5; + margin-bottom: 0; + } + + .assistant-composer textarea { + font-size: 15px; + } + + .composer-icon-button, + .composer-related-button, + .composer-send-button { + height: 32px; + } + + .composer-send-button { + width: 50px; + } +} + +/* 2K 宽屏但内容区仍偏高时,略收紧(避免 hero 独占过多纵向空间) */ +@media (min-width: 1920px) and (max-height: 1100px) { + .workbench { + --hero-padding-top: 22px; + --hero-title-size: 29px; + --composer-min-height: 114px; + --composer-textarea-height: 50px; + --capability-row-height: 100px; + } +} + +@media (max-width: 1440px) { + .workbench { + grid-template-rows: auto var(--capability-row-height) minmax(0, 1fr); + gap: 10px; + } + + .assistant-hero { + --assistant-art-width: min(620px, 44vw); + --assistant-art-x: 48px; + --assistant-art-y: -10px; + padding: var(--hero-padding-top) 18px var(--hero-padding-bottom) 44px; + } + + .assistant-copy { + width: min(1040px, 92%); + } + + .assistant-copy h1 { + font-size: 33px; + } + + .capability-card { + padding: 17px 12px 17px 22px; + } + + .capability-copy { + padding-left: 14px; + } + + .workbench-content-grid { + grid-template-columns: minmax(300px, 0.92fr) minmax(480px, 1.34fr) minmax(270px, 0.76fr); + gap: 14px; + } + + .workbench-card { + padding: 10px 12px; + } + + .progress-row { + grid-template-columns: minmax(126px, 0.9fr) minmax(270px, 1.35fr) minmax(86px, auto); + gap: 12px; + } +} + +@media (max-width: 1180px) { + .assistant-hero { + --assistant-art-width: min(540px, 50vw); + --assistant-art-x: 36px; + --assistant-art-y: -8px; + background: + linear-gradient(90deg, rgba(255, 255, 255, 0.97) 0%, rgba(255, 255, 255, 0.9) 56%, rgba(255, 255, 255, 0.22) 100%), + linear-gradient(135deg, #ffffff 0%, color-mix(in srgb, var(--workbench-primary-soft) 48%, #ffffff) 58%, color-mix(in srgb, var(--workbench-secondary) 8%, #ffffff) 100%); + } + + .assistant-copy { + width: min(820px, 92%); + } + + .capability-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .workbench-content-grid { + grid-template-columns: 1fr; + } + + .side-column { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 760px) { + .workbench { + height: auto; + grid-template-rows: none; + gap: 14px; + overflow: visible; + } + + .assistant-hero { + min-height: auto; + --assistant-art-width: min(380px, 78vw); + --assistant-art-x: 12px; + --assistant-art-y: -6px; + padding: 24px 18px 20px; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.94) 100%), + color-mix(in srgb, var(--workbench-primary-soft) 22%, #ffffff); + } + + .assistant-copy { + width: 100%; + } + + .assistant-copy h1 { + max-width: 320px; + font-size: 28px; + } + + .assistant-composer { + padding: 14px; + } + + .composer-toolbar { + gap: 8px; + flex-wrap: wrap; + } + + .composer-count { + order: 4; + width: 100%; + margin-left: 0; + } + + .composer-send-button { + margin-left: auto; + } + + .capability-grid, + .side-column { + grid-template-columns: 1fr; + } + + .todo-row, + .progress-row { + grid-template-columns: 1fr; + justify-items: start; + } + + .todo-row { + grid-template-columns: 48px minmax(0, 1fr); + } + + .todo-meta, + .progress-result { + justify-items: start; + } + + .todo-meta { + grid-column: 2; + } + + .progress-steps { + width: 100%; + } +} diff --git a/web/src/assets/styles/components/personal-workbench.css b/web/src/assets/styles/components/personal-workbench.css index 9cace19..609b9d6 100644 --- a/web/src/assets/styles/components/personal-workbench.css +++ b/web/src/assets/styles/components/personal-workbench.css @@ -1,213 +1,213 @@ .workbench { + --hero-padding-top: 26px; + --hero-padding-bottom: 14px; + --hero-title-size: 30px; + --hero-copy-gap: 6px; + --composer-min-height: 122px; + --composer-textarea-height: 54px; + --composer-padding-block: 12px; + --quick-prompts-gap-top: 10px; + --capability-row-height: 104px; + --workbench-ink: var(--ink, #1e293b); + --workbench-text: var(--text, #334155); + --workbench-muted: var(--muted, #64748b); + --workbench-line: var(--line, #e2e8f0); + --workbench-line-strong: var(--line-strong, #cbd5e1); + --workbench-line-soft: color-mix(in srgb, var(--line, #e2e8f0) 58%, #fff); + --workbench-surface: var(--surface, #fff); + --workbench-surface-soft: var(--surface-soft, #f9fbff); + --workbench-primary: var(--theme-primary, #3a7ca5); + --workbench-primary-active: var(--theme-primary-active, #255b7d); + --workbench-primary-soft: var(--theme-primary-soft, #eaf4fa); + --workbench-secondary: var(--theme-secondary, #4f6f9f); + --workbench-chart-blue: var(--chart-blue, #4f6f9f); + --workbench-chart-purple: var(--chart-purple, #6e7fa6); + --workbench-chart-amber: var(--chart-amber, #b58b4c); + + width: 100%; + height: 100%; min-width: 0; display: grid; - gap: 16px; - padding-bottom: 10px; + grid-template-rows: auto var(--capability-row-height) minmax(0, 1fr); + gap: 10px; + overflow: visible; + color: var(--workbench-ink); } +.workbench :where(button, textarea) { + font: inherit; +} + +.workbench, +.workbench * { + box-sizing: border-box; +} + +.workbench :where(button) { + border: 0; + background: transparent; + cursor: pointer; +} + +.workbench :where(button:disabled) { cursor: not-allowed; opacity: 0.7; } + .assistant-hero { + --assistant-art-width: min(680px, 46vw); + --assistant-art-x: 56px; + --assistant-art-y: -12px; position: relative; - overflow: hidden; - display: grid; - grid-template-columns: 228px minmax(0, 1fr); - gap: 18px; - padding: 20px 24px 20px 18px; - border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18); + z-index: 2; + min-height: 0; + overflow: visible; + padding: var(--hero-padding-top) 20px var(--hero-padding-bottom) 52px; + border: 1px solid color-mix(in srgb, var(--workbench-primary) 14%, var(--workbench-line)); + border-radius: 12px; background: - radial-gradient(circle at top left, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.12), transparent 34%), - radial-gradient(circle at right 20%, rgba(59, 130, 246, 0.07), transparent 28%), - linear-gradient(135deg, #f7fbff 0%, #ffffff 48%, #f5fbff 100%); + linear-gradient(90deg, rgba(255, 255, 255, 0.97) 0%, rgba(255, 255, 255, 0.9) 44%, rgba(255, 255, 255, 0.16) 66%, rgba(255, 255, 255, 0.02) 100%), + linear-gradient(135deg, #ffffff 0%, color-mix(in srgb, var(--workbench-primary-soft) 56%, #ffffff) 62%, color-mix(in srgb, var(--workbench-secondary) 8%, #ffffff) 100%); + box-shadow: 0 8px 20px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.06); + isolation: isolate; } -.assistant-hero::before, .assistant-hero::after { content: ""; position: absolute; - border-radius: 999px; - background: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.06); + right: var(--assistant-art-x); + bottom: var(--assistant-art-y); + width: var(--assistant-art-width); + height: calc(100% + 28px); + background: var(--assistant-bg-image) right bottom / auto 112% no-repeat; pointer-events: none; + z-index: 2; } .assistant-hero::before { - right: -48px; - bottom: -58px; - width: 220px; - height: 220px; -} - -.assistant-hero::after { - right: 92px; - top: -44px; - width: 140px; - height: 140px; -} - -.assistant-visual { - position: relative; - min-height: 196px; - display: flex; - align-items: flex-end; - justify-content: flex-start; - padding: 0 0 10px 8px; -} - -.assistant-visual::before { content: ""; position: absolute; - inset: auto auto -78px -58px; - width: 264px; - height: 228px; - border-radius: 50%; - background: radial-gradient(circle at 48% 38%, rgba(255, 255, 255, 0.92) 0%, rgba(224, 242, 254, 0.84) 58%, rgba(224, 242, 254, 0) 100%); + inset: 0; + border-radius: inherit; + background: + linear-gradient(90deg, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0.08) 42%, transparent 58%), + radial-gradient(circle at 84% 62%, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08), transparent 36%); pointer-events: none; -} - -.assistant-visual::after { - content: ""; - position: absolute; - left: 52px; - bottom: 18px; - width: 132px; - height: 18px; - border-radius: 999px; - background: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.14); - filter: blur(12px); - pointer-events: none; -} - -.assistant-glow { - position: absolute; - left: 24px; - bottom: 22px; - width: 176px; - height: 176px; - border-radius: 50%; - background: radial-gradient(circle, rgba(255, 255, 255, 0.98) 0%, rgba(224, 242, 254, 0.9) 58%, rgba(224, 242, 254, 0) 100%); - box-shadow: 0 24px 48px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.12); - pointer-events: none; -} - -.assistant-image { - position: relative; z-index: 1; - width: 184px; - max-width: 100%; - height: auto; - object-fit: contain; - object-position: left bottom; - filter: drop-shadow(0 22px 28px rgba(15, 23, 42, 0.16)); } .assistant-copy { position: relative; - z-index: 1; + z-index: 3; + width: min(1120px, 94%); display: grid; - gap: 10px; - align-content: center; + gap: var(--hero-copy-gap); } -.assistant-copy h3 { - color: #0f172a; - font-size: 26px; - line-height: 1.25; - font-weight: 800; +.assistant-copy h1 { + margin: 0; + color: var(--workbench-ink); + font-size: var(--hero-title-size); + line-height: 1.18; + font-weight: 850; +} + +.assistant-copy h1 span { + color: var(--workbench-primary-active); } .assistant-copy p { - max-width: 760px; - color: #5b6b83; - font-size: 14px; + max-width: 680px; + margin: 0 0 2px; + color: var(--workbench-muted); + font-size: 15px; line-height: 1.6; + font-weight: 600; } -.assistant-input { - display: flex; - align-items: center; - min-height: 48px; - padding: 4px 14px; - border: 1px solid rgba(148, 163, 184, 0.28); - border-radius: 4px; - background: rgba(255, 255, 255, 0.92); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7); +.assistant-file-input { display: none; } + +.assistant-composer { + display: grid; + gap: 6px; + min-height: var(--composer-min-height); + padding: var(--composer-padding-block) 18px 10px; + border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.28); + border-radius: 9px; + background: rgba(255, 255, 255, 0.96); + box-shadow: + 0 8px 18px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.96); + backdrop-filter: blur(4px); } -.assistant-file-input { - display: none; -} - -.assistant-input textarea { +.assistant-composer textarea { + width: 100%; min-width: 0; - flex: 1; - height: 22px; - min-height: 22px; - max-height: 22px; + height: var(--composer-textarea-height); + min-height: var(--composer-textarea-height); + max-height: var(--composer-textarea-height); resize: none; border: 0; - padding: 1px 0; + padding: 0; background: transparent; - color: #0f172a; - font-size: 15px; - line-height: 22px; + color: var(--workbench-ink); + font-size: 16px; + line-height: 1.55; overflow: hidden; } -.assistant-input textarea::placeholder { - color: #94a3b8; +.assistant-composer textarea::placeholder { + color: color-mix(in srgb, var(--workbench-muted) 70%, #ffffff); } -.assistant-input textarea:focus { - outline: none; -} +.assistant-composer textarea:focus { outline: none; } -.hero-action, -.secondary-action, -.ghost-action, -.row-action, -.link-action, -.row-link { - border: 0; - background: transparent; -} - -.hero-action { - height: 40px; - display: inline-flex; - align-items: center; - justify-content: center; - gap: 8px; - padding: 0 16px; - border-radius: 4px; - background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active)); - color: #fff; - font-size: 14px; - font-weight: 800; - white-space: nowrap; - box-shadow: 0 10px 22px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18); -} - -.hero-action .mdi, -.secondary-action .mdi, -.ghost-action .mdi { - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 14px; - line-height: 1; -} - -.hero-action span, -.secondary-action span, -.ghost-action span { - display: inline-flex; - align-items: center; - line-height: 1; -} - -.assistant-tools { +.composer-toolbar { display: flex; align-items: center; - gap: 10px; - flex-wrap: wrap; + gap: 12px; +} + +.composer-icon-button, +.composer-related-button, +.composer-send-button { + display: inline-flex; + align-items: center; + justify-content: center; + height: 36px; + border-radius: 7px; + white-space: nowrap; +} + +.composer-icon-button { + width: 36px; + border: 1px solid var(--workbench-line); + background: var(--workbench-surface); + color: var(--workbench-text); + font-size: 19px; +} + +.composer-related-button { + gap: 8px; + padding: 0 16px; + border: 1px solid var(--workbench-line); + background: var(--workbench-surface); + color: var(--workbench-text); + font-size: 14px; + font-weight: 700; +} + +.composer-count { + margin-left: auto; + color: color-mix(in srgb, var(--workbench-muted) 75%, #ffffff); + font-size: 13px; + font-weight: 650; +} + +.composer-send-button { + width: 56px; + background: var(--theme-gradient-primary); + color: #fff; + font-size: 18px; + box-shadow: 0 10px 20px var(--theme-primary-shadow); } .assistant-file-strip { @@ -221,99 +221,198 @@ .assistant-file-chip { display: inline-flex; align-items: center; - min-height: 30px; - padding: 0 12px; + max-width: 220px; + min-height: 28px; + padding: 0 10px; border-radius: 999px; font-size: 12px; - font-weight: 700; + font-weight: 750; } .assistant-file-note { - background: var(--theme-primary-soft); - color: var(--theme-primary-active); + background: var(--workbench-primary-soft); + color: var(--workbench-primary-active); } .assistant-file-chip { - max-width: 220px; overflow: hidden; + border: 1px solid var(--workbench-line); + background: var(--workbench-surface); + color: var(--workbench-text); text-overflow: ellipsis; white-space: nowrap; - border: 1px solid rgba(148, 163, 184, 0.24); - background: rgba(255, 255, 255, 0.9); - color: #475569; } .assistant-file-clear { - border: 0; - background: transparent; - color: #64748b; + color: var(--workbench-muted); font-size: 12px; - font-weight: 700; - cursor: pointer; + font-weight: 750; } -.ghost-action { - height: 40px; - display: inline-flex; +.quick-prompts { + display: flex; align-items: center; - justify-content: center; - gap: 8px; - padding: 0 16px; - border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.22); - border-radius: 4px; - background: linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(248, 251, 255, 0.92)); - color: var(--theme-primary-active); + gap: 10px; + flex-wrap: wrap; + margin-top: var(--quick-prompts-gap-top); + margin-bottom: 0; + color: var(--workbench-text); font-size: 14px; font-weight: 700; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.9), - 0 6px 14px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08); } -.ghost-action .mdi { - color: var(--theme-primary); +.quick-prompts button { + min-height: 28px; + padding: 0 14px; + border: 1px solid var(--workbench-line); + border-radius: 6px; + background: rgba(255, 255, 255, 0.86); + color: var(--workbench-text); + font-size: 13px; + font-weight: 650; } -.secondary-action { - height: 40px; +.quick-prompts .quick-more { display: inline-flex; align-items: center; - justify-content: center; - gap: 8px; - padding: 0 16px; - border: 1px solid rgba(59, 130, 246, 0.18); - border-radius: 4px; - background: linear-gradient(180deg, rgba(244, 249, 255, 0.96), rgba(234, 244, 255, 0.9)); - color: #1d4ed8; - font-size: 14px; - font-weight: 700; - white-space: nowrap; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.92), - 0 6px 14px rgba(37, 99, 235, 0.08); + gap: 4px; + border-color: transparent; + background: transparent; + color: var(--workbench-primary-active); + font-weight: 800; } -.secondary-action .mdi { - color: #2563eb; -} - -.hero-action:disabled, -.secondary-action:disabled, -.ghost-action:disabled { - cursor: not-allowed; - opacity: 0.68; - box-shadow: none; -} - -.workbench-grid { +.capability-grid { + position: relative; + z-index: 1; display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 20px; + grid-template-columns: repeat(6, minmax(0, 1fr)); + gap: 16px; + min-height: 0; } -.list-panel, -.policy-panel { - padding: 20px 22px; +.capability-card { + position: relative; + isolation: isolate; + display: grid; + grid-template-columns: 40px minmax(0, 1fr) 10px; + align-items: center; + gap: 14px; + min-height: 0; + padding: 17px 12px 17px 26px; + overflow: hidden; + border: 1px solid var(--workbench-line); + border-radius: 8px; + background: var(--workbench-surface); + text-align: left; + box-shadow: + 0 1px 0 rgba(255, 255, 255, 0.98) inset, + 0 6px 16px rgba(15, 23, 42, 0.035); +} + +.capability-card::after { + display: none; +} + +.capability-icon { + width: 40px; + height: 40px; + display: grid; + place-items: center; + border-radius: 9px; + border: 1px solid color-mix(in srgb, var(--capability-color) 20%, #ffffff); + background: var(--capability-soft); + color: var(--capability-color); + font-size: 24px; + box-shadow: 0 6px 14px color-mix(in srgb, var(--capability-color) 10%, transparent); +} + +.capability-copy { + min-width: 0; + display: grid; + gap: 4px; + padding-left: 18px; +} + +.capability-copy strong { + color: var(--workbench-ink); + font-size: 14px; + font-weight: 850; + line-height: 1.25; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.capability-copy small { + overflow: hidden; + color: var(--workbench-muted); + font-size: 12px; + line-height: 1.35; + text-overflow: ellipsis; + white-space: nowrap; +} + +.capability-arrow { + color: color-mix(in srgb, var(--workbench-muted) 68%, #ffffff); + font-size: 18px; +} + +.capability-card--green { + --capability-color: var(--workbench-primary); + --capability-soft: var(--workbench-primary-soft); +} + +.capability-card--blue { + --capability-color: var(--workbench-chart-blue); + --capability-soft: color-mix(in srgb, var(--workbench-chart-blue) 10%, #ffffff); +} + +.capability-card--emerald { + --capability-color: var(--success); + --capability-soft: var(--success-soft); +} + +.capability-card--violet { + --capability-color: var(--workbench-chart-purple); + --capability-soft: color-mix(in srgb, var(--workbench-chart-purple) 10%, #ffffff); +} + +.capability-card--cyan { + --capability-color: var(--workbench-secondary); + --capability-soft: color-mix(in srgb, var(--workbench-secondary) 10%, #ffffff); +} + +.capability-card--amber { + --capability-color: var(--workbench-chart-amber); + --capability-soft: color-mix(in srgb, var(--workbench-chart-amber) 12%, #ffffff); +} + +.workbench-content-grid { + display: grid; + grid-template-columns: minmax(360px, 0.95fr) minmax(560px, 1.4fr) minmax(320px, 0.82fr); + gap: 14px; + align-items: stretch; + min-height: 0; + overflow: hidden; +} + +.workbench-card { + min-height: 0; + height: 100%; + overflow: hidden; + padding: 12px 14px; + border: 1px solid var(--workbench-line); + border-radius: 8px; + background: var(--workbench-surface); + box-shadow: 0 6px 16px rgba(15, 23, 42, 0.035); +} + +.todo-panel, +.progress-panel, +.side-panel { + display: grid; + grid-template-rows: auto minmax(0, 1fr); } .section-head { @@ -321,13 +420,16 @@ align-items: center; justify-content: space-between; gap: 12px; - margin-bottom: 16px; + min-height: 24px; + margin-bottom: 5px; } -.section-head h3 { - color: #0f172a; - font-size: 17px; - font-weight: 700; +.section-head h2 { + margin: 0; + color: var(--workbench-ink); + font-size: 16px; + line-height: 1.25; + font-weight: 850; } .title-with-badge { @@ -337,369 +439,254 @@ min-width: 0; } -.alert-badge { - min-width: 22px; - height: 22px; +.soft-badge { + min-width: 24px; + height: 24px; display: inline-flex; align-items: center; justify-content: center; padding: 0 7px; border-radius: 999px; - background: #ef4444; - color: #fff; - font-size: 12px; - font-weight: 800; - line-height: 1; - box-shadow: 0 6px 14px rgba(239, 68, 68, 0.22); + background: var(--workbench-primary-soft); + color: var(--workbench-primary-active); + font-size: 13px; + font-weight: 850; } .link-action { display: inline-flex; align-items: center; gap: 4px; - color: var(--theme-primary-active); - font-size: 14px; - font-weight: 700; + color: var(--workbench-muted); + font-size: 13px; + font-weight: 800; + white-space: nowrap; } -.list-body { - display: grid; +.muted-link { + color: var(--workbench-muted); } -.todo-row, -.progress-row { +.todo-list, +.progress-list { display: grid; - grid-template-columns: 56px minmax(0, 1fr) auto; - gap: 14px; + min-height: 0; + height: 100%; + grid-auto-rows: minmax(0, 1fr); +} + +.todo-row { + display: grid; + grid-template-columns: 34px minmax(0, 1fr) auto; align-items: center; - padding: 14px 0; - border-top: 1px solid #edf2f7; + gap: 9px; + width: 100%; + padding: 2px 0; + border-top: 1px solid var(--workbench-line-soft); + text-align: left; } .todo-row:first-child, .progress-row:first-child { - padding-top: 4px; + padding-top: 2px; border-top: 0; } +.todo-row :deep(.workbench-list-icon) { + width: 28px; + height: 28px; +} + +.todo-row :deep(.workbench-list-icon__panel) { + border-radius: 12px; +} + +.todo-row :deep(.workbench-list-icon__art), +.todo-row :deep(.workbench-heroicon) { + width: 16px; + height: 16px; +} + .todo-copy { min-width: 0; -} - -.todo-copy strong { - display: block; - color: #0f172a; - font-size: 15px; - font-weight: 700; - line-height: 1.4; -} - -.todo-copy p { - margin-top: 4px; - color: #6b7280; - font-size: 14px; - line-height: 1.5; -} - -.todo-advice { - display: flex; - align-items: flex-start; - gap: 8px; - flex-wrap: wrap; -} - -.todo-advice-label { - display: inline-flex; - align-items: center; - min-height: 22px; - padding: 0 8px; - border-radius: 999px; - background: var(--theme-primary-soft); - color: var(--theme-primary-active); - font-size: 12px; - font-weight: 800; - white-space: nowrap; -} - -.todo-advice-text { - color: #64748b; -} - -.row-action { - height: 38px; - padding: 0 16px; - border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.36); - border-radius: 4px; - color: var(--theme-primary-active); - font-size: 14px; - font-weight: 700; - white-space: nowrap; -} - -.progress-row { - grid-template-columns: 56px minmax(0, 1fr) minmax(84px, auto) minmax(104px, auto); - gap: 14px 16px; -} - -.progress-copy strong { - margin-bottom: 2px; -} - -.progress-amount { - color: #0f172a; - font-size: 20px; - font-weight: 800; - line-height: 1; - text-align: right; - font-variant-numeric: tabular-nums; - white-space: nowrap; -} - -.progress-status { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 104px; - min-height: 34px; - padding: 6px 14px; - border-radius: 999px; - font-size: 13px; - font-weight: 800; - white-space: nowrap; - justify-self: end; -} - -.progress-status.success, -.policy-status.success { - background: var(--success-soft); - color: var(--success); -} - -.progress-status.info, -.policy-status.info { - background: #eff6ff; - color: #3b82f6; -} - -.progress-status.mint { - background: var(--success-soft); - color: var(--success); -} - -.policy-table { - border: 1px solid #e7edf5; - border-radius: 4px; - overflow: hidden; -} - -.policy-row { display: grid; - grid-template-columns: 2.2fr 2.4fr 1fr; - gap: 16px; - align-items: center; - min-height: 56px; - padding: 0 18px; - border-top: 1px solid #edf2f7; + gap: 2px; } -.policy-head { - min-height: 44px; - background: #f8fbff; - color: #64748b; - font-size: 12px; - font-weight: 800; - border-top: 0; -} - -.policy-row strong, -.policy-row span { - min-width: 0; +.todo-copy strong, +.progress-identity strong, +.progress-result strong { overflow: hidden; + color: var(--workbench-ink); + font-size: 13px; + font-weight: 850; + line-height: 1.25; text-overflow: ellipsis; white-space: nowrap; } -.policy-row strong { - color: #0f172a; - font-size: 14px; - font-weight: 700; +.todo-copy small, +.todo-meta small, +.progress-identity small { + overflow: hidden; + color: var(--workbench-muted); + font-size: 11.5px; + line-height: 1.25; + text-overflow: ellipsis; + white-space: nowrap; } -.policy-row span { - color: #64748b; - font-size: 14px; +.todo-meta { + min-width: 96px; + display: grid; + justify-items: end; + gap: 2px; } -.policy-title-cell, -.policy-summary-cell { - justify-self: stretch; +.todo-status, +.progress-status { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 20px; + padding: 0 7px; + border-radius: 4px; + font-size: 11.5px; + font-weight: 850; + white-space: nowrap; +} + +.todo-status--warning, +.progress-status--warning { + background: var(--warning-soft); + color: var(--warning); +} + +.todo-status--success, +.progress-status--success { + background: var(--workbench-primary-soft); + color: var(--workbench-primary-active); +} + +.todo-status--danger { + background: var(--danger-soft); + color: var(--danger); +} + +.todo-status--info { + background: var(--info-soft); + color: var(--info); +} + +.todo-status--orange { + background: var(--warning-soft); + color: var(--warning); +} + +.progress-status--muted { + background: var(--info-soft); + color: var(--workbench-muted); +} + +.progress-row { + display: grid; + grid-template-columns: minmax(138px, 0.9fr) minmax(300px, 1.5fr) minmax(92px, auto); + align-items: center; + gap: 12px; + width: 100%; + padding: 1px 0; + border-top: 1px solid var(--workbench-line-soft); text-align: left; } -.policy-date-cell { - justify-self: center; - text-align: center; +.progress-identity, +.progress-result { + min-width: 0; + display: grid; + gap: 2px; } -@media (max-width: 1320px) { - .assistant-copy h3 { - font-size: 24px; - } - - .policy-row { - grid-template-columns: 1.8fr 1.8fr 1fr; - } +.progress-result { + justify-items: end; } -@media (max-width: 1440px) { - .workbench { - gap: 14px; - } - - .assistant-hero { - gap: 16px; - padding: 18px 20px 18px 16px; - } - - .assistant-copy h3 { - font-size: 24px; - } - - .assistant-visual { - min-height: 184px; - } - - .assistant-image { - width: 172px; - } - - .workbench-grid { - gap: 16px; - } - - .list-panel, - .policy-panel { - padding: 18px 20px; - } - - .policy-row { - min-height: 52px; - padding: 0 16px; - } +.progress-steps { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + align-items: start; } -@media (max-width: 1080px) { - .assistant-hero { - grid-template-columns: 1fr; - gap: 8px; - } - - .assistant-visual { - min-height: 188px; - justify-content: center; - padding: 0 0 8px; - } - - .assistant-visual::before, - .assistant-visual::after, - .assistant-glow { - left: 50%; - transform: translateX(-50%); - } - - .assistant-visual::before { - inset: auto auto -82px 50%; - } - - .assistant-image { - width: 176px; - } - - .workbench-grid { - grid-template-columns: 1fr; - } +.progress-step { + position: relative; + display: grid; + justify-items: center; + gap: 1px; + color: color-mix(in srgb, var(--workbench-muted) 64%, #ffffff); } -@media (max-width: 860px) { - .assistant-hero, - .list-panel, - .policy-panel { - padding: 18px; - } - - .assistant-input { - flex-direction: column; - align-items: stretch; - padding: 14px; - } - - .assistant-visual { - min-height: 160px; - } - - .assistant-glow { - width: 148px; - height: 148px; - } - - .assistant-image { - width: 150px; - } - - .assistant-input textarea { - height: 40px; - min-height: 40px; - max-height: 40px; - line-height: 1.5; - } - - .hero-action, - .secondary-action, - .ghost-action, - .row-action { - width: 100%; - justify-content: center; - } - - .assistant-file-chip { - max-width: 100%; - } - - .todo-row, - .progress-row { - grid-template-columns: 56px minmax(0, 1fr); - } - - .progress-amount { - grid-column: 2; - text-align: left; - font-size: 18px; - } - - .row-action, - .progress-status { - grid-column: 2; - justify-self: start; - } - - .policy-table { - border: 0; - border-radius: 0; - } - - .policy-head { - display: none; - } - - .policy-row { - grid-template-columns: 1fr; - gap: 8px; - padding: 16px 0; - border-top: 1px solid #edf2f7; - } - - .policy-row strong, - .policy-row span { - white-space: normal; - } +.progress-step::before { + content: ""; + position: absolute; + top: 8px; + left: calc(-50% + 12px); + right: calc(50% + 12px); + height: 2px; + background: var(--workbench-line); +} + +.progress-step:first-child::before { display: none; } + +.progress-step.is-done::before, +.progress-step.is-current::before { + background: var(--workbench-primary); +} + +.progress-step i { + position: relative; + z-index: 1; + width: 16px; + height: 16px; + display: grid; + place-items: center; + border: 2px solid var(--workbench-line); + border-radius: 999px; + background: var(--workbench-surface); + color: var(--workbench-line-strong, #cbd5e1); + font-size: 12px; + line-height: 1; +} + +.progress-step.is-done i { + border-color: var(--workbench-primary); + background: var(--workbench-primary-soft); + color: var(--workbench-primary-active); +} + +.progress-step.is-current i { + border-color: var(--workbench-primary-active); + background: var(--theme-primary-light-9); + color: var(--workbench-primary-active); +} + +.progress-step small { + color: currentColor; + font-size: 10px; + font-weight: 750; + line-height: 1.2; + white-space: nowrap; +} + +.progress-step.is-done, +.progress-step.is-current { + color: var(--workbench-ink); +} + +.capability-card:hover, +.todo-row:hover, +.progress-row:hover, +.quick-prompts button:hover, +.composer-icon-button:hover, +.composer-related-button:hover { + border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.24); + color: var(--workbench-primary-active); } diff --git a/web/src/assets/styles/components/sidebar-rail.css b/web/src/assets/styles/components/sidebar-rail.css index dcbc8d3..90dfbd1 100644 --- a/web/src/assets/styles/components/sidebar-rail.css +++ b/web/src/assets/styles/components/sidebar-rail.css @@ -207,6 +207,11 @@ stroke-linejoin: round; } +.nav-btn :deep(svg text) { + fill: currentColor; + stroke: none; +} + .nav-label { flex: 1; min-width: 0; diff --git a/web/src/assets/styles/views/audit-view-part2.css b/web/src/assets/styles/views/audit-view-part2.css index 30872c6..c1392be 100644 --- a/web/src/assets/styles/views/audit-view-part2.css +++ b/web/src/assets/styles/views/audit-view-part2.css @@ -1810,6 +1810,40 @@ background: #ffffff; } +.digital-worker-source-card { + min-height: 0; +} + +.digital-worker-source-card .card-head { + align-items: center; +} + +.digital-worker-source-editor { + width: 100%; + min-height: 360px; + resize: vertical; + border: 1px solid #dbe4ef; + border-radius: 8px; + padding: 14px 16px; + background: #0f172a; + color: #e2e8f0; + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 12.5px; + line-height: 1.7; + outline: none; +} + +.digital-worker-source-editor:focus { + border-color: #2563eb; + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.14); +} + +.digital-worker-source-editor[readonly] { + color: #cbd5e1; + background: #1e293b; + cursor: default; +} + @media (max-width: 760px) { .risk-rule-create-form, .json-risk-meta-grid { diff --git a/web/src/assets/styles/views/digital-employees-view.css b/web/src/assets/styles/views/digital-employees-view.css new file mode 100644 index 0000000..0ff95cc --- /dev/null +++ b/web/src/assets/styles/views/digital-employees-view.css @@ -0,0 +1,94 @@ +.digital-employees-view { + height: 100%; + min-height: 0; +} + +.digital-employees-list { + height: 100%; +} + +.digital-employees-list .table-wrap { + min-height: 0; +} + +.digital-employees-table { + min-width: 1060px; + table-layout: fixed; +} + +.digital-employees-table .col-skill { width: 27%; } +.digital-employees-table .col-schedule { width: 16%; } +.digital-employees-table .col-mode { width: 12%; } +.digital-employees-table .col-skill-type { width: 11%; } +.digital-employees-table .col-status { width: 11%; } +.digital-employees-table .col-enabled { width: 11%; } +.digital-employees-table .col-updated { width: 12%; } + +.digital-employees-table td { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.digital-employees-table tbody tr { + cursor: pointer; +} + +.digital-refresh-action i { + font-size: 16px; +} + +.skill-type-pill { + border-color: #dbeafe; + background: #eff6ff; + color: #1d4ed8; +} + +.digital-employee-detail { + height: 100%; +} + +.digital-employee-detail .detail-scroll { + min-height: 0; + overflow: auto; +} + +.digital-employee-detail-actions .detail-action-group { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 10px; + flex-wrap: wrap; +} + +.digital-employee-detail-actions .success-action { + border-color: var(--success-line); + background: var(--success-soft); + color: var(--success-hover); +} + +.digital-employee-detail-actions .enable-action.is-on { + border-color: #fed7aa; + background: #fff7ed; + color: #ea580c; +} + +@media (max-width: 980px) { + .digital-employees-table { + min-width: 1040px; + } + + .digital-employee-detail-actions { + align-items: stretch; + flex-direction: column; + } + + .digital-employee-detail-actions .detail-action-group { + justify-content: stretch; + } + + .digital-employee-detail-actions .detail-action-group button { + flex: 1 1 0; + justify-content: center; + } +} diff --git a/web/src/assets/styles/views/policies-view.css b/web/src/assets/styles/views/policies-view.css index f0fd85e..7677fc2 100644 --- a/web/src/assets/styles/views/policies-view.css +++ b/web/src/assets/styles/views/policies-view.css @@ -258,7 +258,7 @@ table { width: 100%; - min-width: 690px; + min-width: 780px; border-collapse: collapse; } @@ -365,10 +365,9 @@ th { .state-cell { display: grid; justify-items: center; - gap: 6px; } -.state-time { +.ingest-time-cell { color: #64748b; font-size: 11px; line-height: 1.4; diff --git a/web/src/components/audit/AuditDigitalEmployeeDetail.vue b/web/src/components/audit/AuditDigitalEmployeeDetail.vue new file mode 100644 index 0000000..d98d5c2 --- /dev/null +++ b/web/src/components/audit/AuditDigitalEmployeeDetail.vue @@ -0,0 +1,105 @@ + + + + + + diff --git a/web/src/components/audit/DigitalEmployeeScheduleDialog.vue b/web/src/components/audit/DigitalEmployeeScheduleDialog.vue new file mode 100644 index 0000000..3bf18bc --- /dev/null +++ b/web/src/components/audit/DigitalEmployeeScheduleDialog.vue @@ -0,0 +1,139 @@ + + + + + diff --git a/web/src/components/business/PersonalWorkbench.vue b/web/src/components/business/PersonalWorkbench.vue index 86dc334..86d51dd 100644 --- a/web/src/components/business/PersonalWorkbench.vue +++ b/web/src/components/business/PersonalWorkbench.vue @@ -1,37 +1,71 @@ -