feat: 新增数字员工管理页面与工作台首页重构

后端优化 agent 资产种子初始化和常量配置,前端新增数字员工
视图和调度对话框组件,重构个人工作台首页布局和洞察面板,
完善审计页面数字员工详情和运行时模型,优化侧边栏导航和图
标配置,新增工作台摘要和工作台数据模块,补充单元测试。
This commit is contained in:
caoxiaozhu
2026-05-28 09:30:34 +08:00
parent d4d5d40569
commit 04cd6d0f81
38 changed files with 3413 additions and 1301 deletions

View File

@@ -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
):

View File

@@ -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="初始化制度知识与规则草稿形成任务。",

View File

@@ -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="初始化制度知识与规则草稿形成任务。",

View File

@@ -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",