style: 全局 UI 主题皮肤重构与样式模块化
引入 Element Plus 主题定制和主题皮肤 composable,将全局 样式拆分为组件级独立 CSS 文件(侧边栏、顶栏、工作台等), 统一色彩变量和间距规范,重构所有视图和组件样式以适配新 主题系统,优化图表和知识图谱组件视觉表现,提取审计和差 旅报销相关子组件。
This commit is contained in:
@@ -14,13 +14,13 @@
|
|||||||
"updated_at": "2026-05-17T09:28:28.999515+00:00",
|
"updated_at": "2026-05-17T09:28:28.999515+00:00",
|
||||||
"uploaded_by": "admin",
|
"uploaded_by": "admin",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.726523+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:08.579777+00:00",
|
||||||
"ingest_completed_at": "2026-05-17T10:01:33.272539+00:00",
|
"ingest_completed_at": "2026-05-17T10:01:33.272539+00:00",
|
||||||
"ingest_document_name": "远光《公司支出管理办法(2024)》.pdf",
|
"ingest_document_name": "远光《公司支出管理办法(2024)》.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-17T09:28:28.999515+00:00",
|
"ingest_document_updated_at": "2026-05-17T09:28:28.999515+00:00",
|
||||||
"ingest_document_sha256": "67a74538bce0dec71ccbb947256cc2c9c0e672d148de49406b967ae1379dbece",
|
"ingest_document_sha256": "67a74538bce0dec71ccbb947256cc2c9c0e672d148de49406b967ae1379dbece",
|
||||||
"ingest_agent_run_id": "run_3a0b0ecb941b4c8e"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "c7601043d9944ef2bcf4d3f67ed253f7",
|
"id": "c7601043d9944ef2bcf4d3f67ed253f7",
|
||||||
@@ -35,13 +35,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:22.328877+00:00",
|
"updated_at": "2026-05-22T07:00:22.328877+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.731130+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:09.863684+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T09:22:25.565409+00:00",
|
"ingest_completed_at": "2026-05-22T09:22:25.565409+00:00",
|
||||||
"ingest_document_name": "远光软件会计科目使用说明.xlsx",
|
"ingest_document_name": "远光软件会计科目使用说明.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:22.328877+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:22.328877+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_8c1ab050c9734d96"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "b0277cd76034437997fbf5219662725a",
|
"id": "b0277cd76034437997fbf5219662725a",
|
||||||
@@ -56,13 +56,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:22.011016+00:00",
|
"updated_at": "2026-05-22T07:00:22.011016+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.735501+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:00:50.652735+00:00",
|
||||||
"ingest_completed_at": "2026-05-23T14:30:33.605531+00:00",
|
"ingest_completed_at": "2026-05-23T14:30:33.605531+00:00",
|
||||||
"ingest_document_name": "远光软件财务基础知识手册.docx",
|
"ingest_document_name": "远光软件财务基础知识手册.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:22.011016+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:22.011016+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_8c1ab050c9734d96"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "23f56f159a3e4bc3b2338056544120dd",
|
"id": "23f56f159a3e4bc3b2338056544120dd",
|
||||||
@@ -77,13 +77,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:22.352133+00:00",
|
"updated_at": "2026-05-22T07:00:22.352133+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.739842+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:00:51.908821+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T09:23:11.334499+00:00",
|
"ingest_completed_at": "2026-05-22T09:23:11.334499+00:00",
|
||||||
"ingest_document_name": "远光软件财务术语解释手册.docx",
|
"ingest_document_name": "远光软件财务术语解释手册.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:22.352133+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:22.352133+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_8c1ab050c9734d96"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "09fbcae74d3b41e498a47e05b45262cb",
|
"id": "09fbcae74d3b41e498a47e05b45262cb",
|
||||||
@@ -98,13 +98,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:22.304623+00:00",
|
"updated_at": "2026-05-22T07:00:22.304623+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.744555+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:13.581834+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T09:24:18.933073+00:00",
|
"ingest_completed_at": "2026-05-22T09:24:18.933073+00:00",
|
||||||
"ingest_document_name": "远光软件高新技术企业税收优惠政策汇总.pdf",
|
"ingest_document_name": "远光软件高新技术企业税收优惠政策汇总.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:22.304623+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:22.304623+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_8c1ab050c9734d96"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "5fb3c63fbfe244a280cf3316a20150cd",
|
"id": "5fb3c63fbfe244a280cf3316a20150cd",
|
||||||
@@ -119,13 +119,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.153373+00:00",
|
"updated_at": "2026-05-22T07:00:18.153373+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.762391+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:00:53.906324+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:01:43.168774+00:00",
|
"ingest_completed_at": "2026-05-22T16:01:43.168774+00:00",
|
||||||
"ingest_document_name": "远光软件公司内部控制基本规范.pdf",
|
"ingest_document_name": "远光软件公司内部控制基本规范.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.153373+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.153373+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "f4ae48231a974240bbaf6c9f3bfd4160",
|
"id": "f4ae48231a974240bbaf6c9f3bfd4160",
|
||||||
@@ -140,13 +140,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.190399+00:00",
|
"updated_at": "2026-05-22T07:00:18.190399+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.773116+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:00:55.339114+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:03:00.735908+00:00",
|
"ingest_completed_at": "2026-05-22T16:03:00.735908+00:00",
|
||||||
"ingest_document_name": "远光软件公司合同管理制度.docx",
|
"ingest_document_name": "远光软件公司合同管理制度.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.190399+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.190399+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "b1d08d6a9dc6404aba9098f3b7287353",
|
"id": "b1d08d6a9dc6404aba9098f3b7287353",
|
||||||
@@ -161,13 +161,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:17.798679+00:00",
|
"updated_at": "2026-05-22T07:00:17.798679+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.784020+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:00:56.741808+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:03:46.921675+00:00",
|
"ingest_completed_at": "2026-05-22T16:03:46.921675+00:00",
|
||||||
"ingest_document_name": "远光软件公司财务管理制度总则.docx",
|
"ingest_document_name": "远光软件公司财务管理制度总则.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:17.798679+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:17.798679+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "c87fc4aabe524c6c81862c20aabe434c",
|
"id": "c87fc4aabe524c6c81862c20aabe434c",
|
||||||
@@ -182,13 +182,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.531598+00:00",
|
"updated_at": "2026-05-22T07:00:18.531598+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.799323+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:19.014702+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:04:58.719410+00:00",
|
"ingest_completed_at": "2026-05-22T16:04:58.719410+00:00",
|
||||||
"ingest_document_name": "远光软件公司资产管理制度.pdf",
|
"ingest_document_name": "远光软件公司资产管理制度.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.531598+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.531598+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "13181df0179a4bacb12a2f65e3772d9b",
|
"id": "13181df0179a4bacb12a2f65e3772d9b",
|
||||||
@@ -203,13 +203,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.221073+00:00",
|
"updated_at": "2026-05-22T07:00:18.221073+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.814611+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:00:59.485821+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:06:08.172318+00:00",
|
"ingest_completed_at": "2026-05-22T16:06:08.172318+00:00",
|
||||||
"ingest_document_name": "远光软件公司采购管理办法.xlsx",
|
"ingest_document_name": "远光软件公司采购管理办法.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.221073+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.221073+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "396588b0cdd04c86a61ae0b9bd04e06c",
|
"id": "396588b0cdd04c86a61ae0b9bd04e06c",
|
||||||
@@ -224,13 +224,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:19.734422+00:00",
|
"updated_at": "2026-05-22T07:00:19.734422+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.830249+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:00.774887+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:06:48.466110+00:00",
|
"ingest_completed_at": "2026-05-22T16:06:48.466110+00:00",
|
||||||
"ingest_document_name": "远光软件公司差旅费管理办法.docx",
|
"ingest_document_name": "远光软件公司差旅费管理办法.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:19.734422+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:19.734422+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "fe5f834f94244b77bb62171d580ecee3",
|
"id": "fe5f834f94244b77bb62171d580ecee3",
|
||||||
@@ -245,13 +245,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:20.095824+00:00",
|
"updated_at": "2026-05-22T07:00:20.095824+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.847094+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:02.037101+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:07:23.262328+00:00",
|
"ingest_completed_at": "2026-05-22T16:07:23.262328+00:00",
|
||||||
"ingest_document_name": "远光软件出差审批流程说明.pdf",
|
"ingest_document_name": "远光软件出差审批流程说明.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:20.095824+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:20.095824+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "be3fca61e2be421896405082c93cf86c",
|
"id": "be3fca61e2be421896405082c93cf86c",
|
||||||
@@ -266,13 +266,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:20.128471+00:00",
|
"updated_at": "2026-05-22T07:00:20.128471+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.865452+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:24.076574+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:08:02.190081+00:00",
|
"ingest_completed_at": "2026-05-22T16:08:02.190081+00:00",
|
||||||
"ingest_document_name": "远光软件国际出差管理规定.docx",
|
"ingest_document_name": "远光软件国际出差管理规定.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:20.128471+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:20.128471+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "c4421b3049b244a8a92cc53d502e530f",
|
"id": "c4421b3049b244a8a92cc53d502e530f",
|
||||||
@@ -287,13 +287,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:19.759954+00:00",
|
"updated_at": "2026-05-22T07:00:19.759954+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.888420+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:25.270086+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:09:23.091744+00:00",
|
"ingest_completed_at": "2026-05-22T16:09:23.091744+00:00",
|
||||||
"ingest_document_name": "远光软件差旅费标准速查表.xlsx",
|
"ingest_document_name": "远光软件差旅费标准速查表.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:19.759954+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:19.759954+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "e13cc0a8d6474b6caeeedc49c4304558",
|
"id": "e13cc0a8d6474b6caeeedc49c4304558",
|
||||||
@@ -308,13 +308,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.922298+00:00",
|
"updated_at": "2026-05-22T07:00:18.922298+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.905615+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:26.510710+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:11:04.764727+00:00",
|
"ingest_completed_at": "2026-05-22T16:11:04.764727+00:00",
|
||||||
"ingest_document_name": "远光软件公司发票审核标准.xlsx",
|
"ingest_document_name": "远光软件公司发票审核标准.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.922298+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.922298+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "7170abfdde6f4e6abad2fc987564c2cf",
|
"id": "7170abfdde6f4e6abad2fc987564c2cf",
|
||||||
@@ -329,13 +329,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.560177+00:00",
|
"updated_at": "2026-05-22T07:00:18.560177+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.919568+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:06.719118+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:11:54.017817+00:00",
|
"ingest_completed_at": "2026-05-22T16:11:54.017817+00:00",
|
||||||
"ingest_document_name": "远光软件公司发票管理规范.docx",
|
"ingest_document_name": "远光软件公司发票管理规范.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.560177+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.560177+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "dd0d7b32e832446e8ce9caa06c442685",
|
"id": "dd0d7b32e832446e8ce9caa06c442685",
|
||||||
@@ -350,13 +350,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.888128+00:00",
|
"updated_at": "2026-05-22T07:00:18.888128+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.934348+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:28.865726+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:12:23.821434+00:00",
|
"ingest_completed_at": "2026-05-22T16:12:23.821434+00:00",
|
||||||
"ingest_document_name": "远光软件公司增值税发票操作指南.pdf",
|
"ingest_document_name": "远光软件公司增值税发票操作指南.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.888128+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.888128+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "f268a54ee05e4dfca33fd86bcc077216",
|
"id": "f268a54ee05e4dfca33fd86bcc077216",
|
||||||
@@ -371,13 +371,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.953110+00:00",
|
"updated_at": "2026-05-22T07:00:18.953110+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.949214+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:30.095619+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:13:15.450300+00:00",
|
"ingest_completed_at": "2026-05-22T16:13:15.450300+00:00",
|
||||||
"ingest_document_name": "远光软件公司电子发票管理办法.docx",
|
"ingest_document_name": "远光软件公司电子发票管理办法.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.953110+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.953110+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "f3f74cb65a9a4a16933368218c5e25de",
|
"id": "f3f74cb65a9a4a16933368218c5e25de",
|
||||||
@@ -392,13 +392,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:21.585718+00:00",
|
"updated_at": "2026-05-22T07:00:21.585718+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.963406+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:09.790447+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:13:44.636629+00:00",
|
"ingest_completed_at": "2026-05-22T16:13:44.636629+00:00",
|
||||||
"ingest_document_name": "远光软件企业所得税汇算清缴操作手册.pdf",
|
"ingest_document_name": "远光软件企业所得税汇算清缴操作手册.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:21.585718+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:21.585718+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "56721ca1904b437486a609b85e3d9362",
|
"id": "56721ca1904b437486a609b85e3d9362",
|
||||||
@@ -413,13 +413,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:20.881351+00:00",
|
"updated_at": "2026-05-22T07:00:20.881351+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.976986+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:11.027818+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:14:50.092490+00:00",
|
"ingest_completed_at": "2026-05-22T16:14:50.092490+00:00",
|
||||||
"ingest_document_name": "远光软件公司税务管理制度.docx",
|
"ingest_document_name": "远光软件公司税务管理制度.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:20.881351+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:20.881351+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2460661167ef456699ab259321db4156",
|
"id": "2460661167ef456699ab259321db4156",
|
||||||
@@ -434,13 +434,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:21.606227+00:00",
|
"updated_at": "2026-05-22T07:00:21.606227+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:00.995972+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:33.826025+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:15:56.676286+00:00",
|
"ingest_completed_at": "2026-05-22T16:15:56.676286+00:00",
|
||||||
"ingest_document_name": "远光软件研发费用加计扣除管理办法.xlsx",
|
"ingest_document_name": "远光软件研发费用加计扣除管理办法.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:21.606227+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:21.606227+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "e30f54ea32704fbd9701cc931b447a06",
|
"id": "e30f54ea32704fbd9701cc931b447a06",
|
||||||
@@ -455,13 +455,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:21.202633+00:00",
|
"updated_at": "2026-05-22T07:00:21.202633+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:01.010947+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:13.991763+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:16:06.540773+00:00",
|
"ingest_completed_at": "2026-05-22T16:16:06.540773+00:00",
|
||||||
"ingest_document_name": "远光软件软件产品增值税即征即退操作指南.pdf",
|
"ingest_document_name": "远光软件软件产品增值税即征即退操作指南.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:21.202633+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:21.202633+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2d1cd10154e84cb38640dce31f33b529",
|
"id": "2d1cd10154e84cb38640dce31f33b529",
|
||||||
@@ -476,13 +476,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:22.379307+00:00",
|
"updated_at": "2026-05-22T07:00:22.379307+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:01.025910+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:15.257700+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:23:24.252614+00:00",
|
"ingest_completed_at": "2026-05-22T16:23:24.252614+00:00",
|
||||||
"ingest_document_name": "远光软件公司预算管理制度.docx",
|
"ingest_document_name": "远光软件公司预算管理制度.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:22.379307+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:22.379307+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "229b3a79fef14360ba3cbd0a55e5e20c",
|
"id": "229b3a79fef14360ba3cbd0a55e5e20c",
|
||||||
@@ -497,13 +497,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:22.760169+00:00",
|
"updated_at": "2026-05-22T07:00:22.760169+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:01.044022+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:16.510610+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:23:29.997956+00:00",
|
"ingest_completed_at": "2026-05-22T16:23:29.997956+00:00",
|
||||||
"ingest_document_name": "远光软件年度预算编制指南.pdf",
|
"ingest_document_name": "远光软件年度预算编制指南.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:22.760169+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:22.760169+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "a40da5544dea4efcade070274b84a54e",
|
"id": "a40da5544dea4efcade070274b84a54e",
|
||||||
@@ -518,13 +518,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:22.848272+00:00",
|
"updated_at": "2026-05-22T07:00:22.848272+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.402454+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:38.728430+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:24:37.382612+00:00",
|
"ingest_completed_at": "2026-05-22T16:24:37.382612+00:00",
|
||||||
"ingest_document_name": "远光软件预算执行分析报告模板.docx",
|
"ingest_document_name": "远光软件预算执行分析报告模板.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:22.848272+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:22.848272+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "dcd982e40ce94105824e59ecbbae75cb",
|
"id": "dcd982e40ce94105824e59ecbbae75cb",
|
||||||
@@ -539,13 +539,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:22.803708+00:00",
|
"updated_at": "2026-05-22T07:00:22.803708+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.417444+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:19.050297+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:24:45.161319+00:00",
|
"ingest_completed_at": "2026-05-22T16:24:45.161319+00:00",
|
||||||
"ingest_document_name": "远光软件预算编制模板.xlsx",
|
"ingest_document_name": "远光软件预算编制模板.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:22.803708+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:22.803708+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "79cb9276398b4216ba17d5623aadf75f",
|
"id": "79cb9276398b4216ba17d5623aadf75f",
|
||||||
@@ -560,13 +560,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:21.971983+00:00",
|
"updated_at": "2026-05-22T07:00:21.971983+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.433923+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:20.323058+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:25:33.968414+00:00",
|
"ingest_completed_at": "2026-05-22T16:25:33.968414+00:00",
|
||||||
"ingest_document_name": "远光软件财务共享服务SLA标准.xlsx",
|
"ingest_document_name": "远光软件财务共享服务SLA标准.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:21.971983+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:21.971983+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "f841ca416b5d404994a7c4a310e35569",
|
"id": "f841ca416b5d404994a7c4a310e35569",
|
||||||
@@ -581,13 +581,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:21.634300+00:00",
|
"updated_at": "2026-05-22T07:00:21.634300+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.450037+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:21.585474+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:26:05.301987+00:00",
|
"ingest_completed_at": "2026-05-22T16:26:05.301987+00:00",
|
||||||
"ingest_document_name": "远光软件财务共享服务中心运营管理办法.docx",
|
"ingest_document_name": "远光软件财务共享服务中心运营管理办法.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:21.634300+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:21.634300+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "d1ad784de58a4c4a802a0b9fbce29f62",
|
"id": "d1ad784de58a4c4a802a0b9fbce29f62",
|
||||||
@@ -602,13 +602,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:21.945868+00:00",
|
"updated_at": "2026-05-22T07:00:21.945868+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.471635+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:43.752235+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:26:54.048075+00:00",
|
"ingest_completed_at": "2026-05-22T16:26:54.048075+00:00",
|
||||||
"ingest_document_name": "远光软件财务共享服务操作手册.pdf",
|
"ingest_document_name": "远光软件财务共享服务操作手册.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:21.945868+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:21.945868+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ce50d015861f4633a634a2eae416fa2e",
|
"id": "ce50d015861f4633a634a2eae416fa2e",
|
||||||
@@ -623,13 +623,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:19.662743+00:00",
|
"updated_at": "2026-05-22T07:00:19.662743+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.489793+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:24.093834+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:27:31.775974+00:00",
|
"ingest_completed_at": "2026-05-22T16:27:31.775974+00:00",
|
||||||
"ingest_document_name": "远光软件报销流程培训手册.pdf",
|
"ingest_document_name": "远光软件报销流程培训手册.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:19.662743+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:19.662743+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "56a0e13b705e49468d46629f3b5f691a",
|
"id": "56a0e13b705e49468d46629f3b5f691a",
|
||||||
@@ -644,13 +644,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:19.323921+00:00",
|
"updated_at": "2026-05-22T07:00:19.323921+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.505506+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:25.246857+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:27:44.244066+00:00",
|
"ingest_completed_at": "2026-05-22T16:27:44.244066+00:00",
|
||||||
"ingest_document_name": "远光软件新员工财务培训课件.pdf",
|
"ingest_document_name": "远光软件新员工财务培训课件.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:19.323921+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:19.323921+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "22ef5d13bb5e4307a8097628eaa3d398",
|
"id": "22ef5d13bb5e4307a8097628eaa3d398",
|
||||||
@@ -665,13 +665,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:18.988700+00:00",
|
"updated_at": "2026-05-22T07:00:18.988700+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.520887+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:26.471932+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:28:24.573683+00:00",
|
"ingest_completed_at": "2026-05-22T16:28:24.573683+00:00",
|
||||||
"ingest_document_name": "远光软件财务制度培训手册.docx",
|
"ingest_document_name": "远光软件财务制度培训手册.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:18.988700+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:18.988700+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "78d1a28f1c934f46b762fb1466d4be32",
|
"id": "78d1a28f1c934f46b762fb1466d4be32",
|
||||||
@@ -686,13 +686,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:19.686485+00:00",
|
"updated_at": "2026-05-22T07:00:19.686485+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.542919+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:48.525207+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:29:03.349502+00:00",
|
"ingest_completed_at": "2026-05-22T16:29:03.349502+00:00",
|
||||||
"ingest_document_name": "远光软件财务培训课程安排.xlsx",
|
"ingest_document_name": "远光软件财务培训课程安排.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:19.686485+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:19.686485+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "91fbf156593a4dcc956780962195ffd7",
|
"id": "91fbf156593a4dcc956780962195ffd7",
|
||||||
@@ -707,13 +707,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:20.476077+00:00",
|
"updated_at": "2026-05-22T07:00:20.476077+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.558881+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:49.746825+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:29:29.050791+00:00",
|
"ingest_completed_at": "2026-05-22T16:29:29.050791+00:00",
|
||||||
"ingest_document_name": "远光软件报销问题处理指引.xlsx",
|
"ingest_document_name": "远光软件报销问题处理指引.xlsx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:20.476077+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:20.476077+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "a24793b7f7de4749a7c531d1713a4a2b",
|
"id": "a24793b7f7de4749a7c531d1713a4a2b",
|
||||||
@@ -728,13 +728,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:20.453567+00:00",
|
"updated_at": "2026-05-22T07:00:20.453567+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.575410+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:30.343781+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:35:03.548506+00:00",
|
"ingest_completed_at": "2026-05-22T16:35:03.548506+00:00",
|
||||||
"ingest_document_name": "远光软件财务制度问答汇总.pdf",
|
"ingest_document_name": "远光软件财务制度问答汇总.pdf",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:20.453567+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:20.453567+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "3acd9c2df63b4a438c7eab876269b25d",
|
"id": "3acd9c2df63b4a438c7eab876269b25d",
|
||||||
@@ -749,13 +749,13 @@
|
|||||||
"updated_at": "2026-05-22T07:00:20.158497+00:00",
|
"updated_at": "2026-05-22T07:00:20.158497+00:00",
|
||||||
"uploaded_by": "系统导入",
|
"uploaded_by": "系统导入",
|
||||||
"version_number": 1,
|
"version_number": 1,
|
||||||
"ingest_status": 1,
|
"ingest_status": 4,
|
||||||
"ingest_status_updated_at": "2026-05-26T02:39:17.593165+00:00",
|
"ingest_status_updated_at": "2026-05-26T16:01:31.573128+00:00",
|
||||||
"ingest_completed_at": "2026-05-22T16:35:27.056080+00:00",
|
"ingest_completed_at": "2026-05-22T16:35:27.056080+00:00",
|
||||||
"ingest_document_name": "远光软件财务报销常见问题解答.docx",
|
"ingest_document_name": "远光软件财务报销常见问题解答.docx",
|
||||||
"ingest_document_updated_at": "2026-05-22T07:00:20.158497+00:00",
|
"ingest_document_updated_at": "2026-05-22T07:00:20.158497+00:00",
|
||||||
"ingest_document_sha256": "",
|
"ingest_document_sha256": "",
|
||||||
"ingest_agent_run_id": "run_655cdac08d3d4a7f"
|
"ingest_agent_run_id": "run_7236fb72747742a3"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
276
web/package-lock.json
generated
276
web/package-lock.json
generated
@@ -9,14 +9,14 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/g6": "^5.1.1",
|
"@antv/g6": "^5.1.1",
|
||||||
"@primevue/themes": "^4.5.4",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"@vitejs/plugin-vue": "^5.2.4",
|
"@vitejs/plugin-vue": "^5.2.4",
|
||||||
"@vueuse/motion": "^3.0.3",
|
"@vueuse/motion": "^3.0.3",
|
||||||
"chart.js": "^4.5.1",
|
"chart.js": "^4.5.1",
|
||||||
|
"element-plus": "^2.14.0",
|
||||||
"markdown-it": "^14.1.1",
|
"markdown-it": "^14.1.1",
|
||||||
"pg": "^8.13.1",
|
"pg": "^8.13.1",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primevue": "^4.5.5",
|
|
||||||
"vite": "^5.4.19",
|
"vite": "^5.4.19",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-chartjs": "^5.3.3",
|
"vue-chartjs": "^5.3.3",
|
||||||
@@ -343,6 +343,24 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@ctrl/tinycolor": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@element-plus/icons-vue": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.21.5",
|
"version": "0.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||||
@@ -711,6 +729,31 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@floating-ui/core": {
|
||||||
|
"version": "1.7.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz",
|
||||||
|
"integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/utils": "^0.2.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/dom": {
|
||||||
|
"version": "1.7.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.6.tgz",
|
||||||
|
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/core": "^1.7.5",
|
||||||
|
"@floating-ui/utils": "^0.2.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/utils": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz",
|
||||||
|
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.13",
|
"version": "0.3.13",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||||
@@ -799,86 +842,15 @@
|
|||||||
"node": ">=18.12.0"
|
"node": ">=18.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@primeuix/styled": {
|
"node_modules/@popperjs/core": {
|
||||||
"version": "0.7.4",
|
"name": "@sxzz/popperjs-es",
|
||||||
"resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.7.4.tgz",
|
"version": "2.11.8",
|
||||||
"integrity": "sha512-QSO/NpOQg8e9BONWRBx9y8VGMCMYz0J/uKfNJEya/RGEu7ARx0oYW0ugI1N3/KB1AAvyGxzKBzGImbwg0KUiOQ==",
|
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz",
|
||||||
|
"integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"funding": {
|
||||||
"@primeuix/utils": "^0.6.1"
|
"type": "opencollective",
|
||||||
},
|
"url": "https://opencollective.com/popperjs"
|
||||||
"engines": {
|
|
||||||
"node": ">=12.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@primeuix/styles": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@primeuix/styles/-/styles-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-2ykAB6BaHzR/6TwF8ShpJTsZrid6cVIEBVlookSdvOdmlWuevGu5vWOScgIwqWwlZcvkFYAGR/SUV3OHCTBMdw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@primeuix/styled": "^0.7.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@primeuix/themes": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@primeuix/themes/-/themes-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-3fS1883mtCWhgUgNf/feiaaDSOND4EBIOu9tZnzJlJ8QtYyL6eFLcA6V3ymCWqLVXQ1+lTVEZv1gl47FIdXReg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@primeuix/styled": "^0.7.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@primeuix/utils": {
|
|
||||||
"version": "0.6.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@primeuix/utils/-/utils-0.6.4.tgz",
|
|
||||||
"integrity": "sha512-pZ5f+vj7wSzRhC7KoEQRU5fvYAe+RP9+m39CTscZ3UywCD1Y2o6Fe1rRgklMPSkzUcty2jzkA0zMYkiJBD1hgg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@primevue/core": {
|
|
||||||
"version": "4.5.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.5.5.tgz",
|
|
||||||
"integrity": "sha512-JpkXhq1ddc70JdsC3CC4dM+UbeeWuCW/8DpS9dNBfrOk824TLSlRlMEGFyVKqRMn5WPQvYLiy3xXfLQeNdSqhQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@primeuix/styled": "^0.7.4",
|
|
||||||
"@primeuix/utils": "^0.6.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.11.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"vue": "^3.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@primevue/icons": {
|
|
||||||
"version": "4.5.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.5.5.tgz",
|
|
||||||
"integrity": "sha512-eteOhTdAOXEYE9qW1AOrBBgDxQ2szHJxSkEK1XVdV2TKxGM5FQf03Ovms0VDyZTc16XBIgvwYjXJQS0BPbhPaA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@primeuix/utils": "^0.6.2",
|
|
||||||
"@primevue/core": "4.5.5"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@primevue/themes": {
|
|
||||||
"version": "4.5.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@primevue/themes/-/themes-4.5.4.tgz",
|
|
||||||
"integrity": "sha512-rUFZxMHLanTZdvZq4zgZPk+KRBZ3s7fE3bBK32OrZBkHQhEJmkJ7Ftd4w4QFlXyz1B7c+k5invZiOOCjwHXg9Q==",
|
|
||||||
"deprecated": "Deprecated. This package is no longer maintained. Please migrate to @primeuix/themes: https://www.npmjs.com/package/@primeuix/themes",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@primeuix/styled": "^0.7.4",
|
|
||||||
"@primeuix/themes": "^2.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.11.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
@@ -1347,6 +1319,21 @@
|
|||||||
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
|
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/lodash": {
|
||||||
|
"version": "4.17.24",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz",
|
||||||
|
"integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/lodash-es": {
|
||||||
|
"version": "4.17.12",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
|
||||||
|
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/lodash": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/web-bluetooth": {
|
"node_modules/@types/web-bluetooth": {
|
||||||
"version": "0.0.21",
|
"version": "0.0.21",
|
||||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
|
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
|
||||||
@@ -1561,6 +1548,12 @@
|
|||||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||||
"license": "Python-2.0"
|
"license": "Python-2.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/async-validator": {
|
||||||
|
"version": "4.2.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
|
||||||
|
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/base64-arraybuffer": {
|
"node_modules/base64-arraybuffer": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
||||||
@@ -2004,6 +1997,12 @@
|
|||||||
"lodash": "^4.17.15"
|
"lodash": "^4.17.15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dayjs": {
|
||||||
|
"version": "1.11.21",
|
||||||
|
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.21.tgz",
|
||||||
|
"integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/defu": {
|
"node_modules/defu": {
|
||||||
"version": "6.1.7",
|
"version": "6.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz",
|
||||||
@@ -2030,6 +2029,70 @@
|
|||||||
"url": "https://dotenvx.com"
|
"url": "https://dotenvx.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/element-plus": {
|
||||||
|
"version": "2.14.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.14.0.tgz",
|
||||||
|
"integrity": "sha512-POgH+TtoreaEKWqYYAVQyE6i8rQMEFqAEublyF29dBA5yASWPLKY6EzfeqBTr2Uv26mPss4vSrMrNPyaK7LX5w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@ctrl/tinycolor": "^4.2.0",
|
||||||
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
|
"@floating-ui/dom": "^1.0.1",
|
||||||
|
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.8",
|
||||||
|
"@types/lodash": "^4.17.24",
|
||||||
|
"@types/lodash-es": "^4.17.12",
|
||||||
|
"@vueuse/core": "14.3.0",
|
||||||
|
"async-validator": "^4.2.5",
|
||||||
|
"dayjs": "^1.11.20",
|
||||||
|
"lodash": "^4.18.1",
|
||||||
|
"lodash-es": "^4.18.1",
|
||||||
|
"lodash-unified": "^1.0.3",
|
||||||
|
"memoize-one": "^6.0.0",
|
||||||
|
"normalize-wheel-es": "^1.2.0",
|
||||||
|
"vue-component-type-helpers": "^3.2.8"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.3.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/element-plus/node_modules/@vueuse/core": {
|
||||||
|
"version": "14.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.3.0.tgz",
|
||||||
|
"integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/web-bluetooth": "^0.0.21",
|
||||||
|
"@vueuse/metadata": "14.3.0",
|
||||||
|
"@vueuse/shared": "14.3.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/element-plus/node_modules/@vueuse/metadata": {
|
||||||
|
"version": "14.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.3.0.tgz",
|
||||||
|
"integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/element-plus/node_modules/@vueuse/shared": {
|
||||||
|
"version": "14.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.3.0.tgz",
|
||||||
|
"integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/entities": {
|
"node_modules/entities": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
|
||||||
@@ -2292,6 +2355,23 @@
|
|||||||
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
|
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash-es": {
|
||||||
|
"version": "4.18.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz",
|
||||||
|
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash-unified": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/lodash-es": "*",
|
||||||
|
"lodash": "*",
|
||||||
|
"lodash-es": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.21",
|
"version": "0.30.21",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||||
@@ -2336,6 +2416,12 @@
|
|||||||
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
|
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/memoize-one": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ml-array-max": {
|
"node_modules/ml-array-max": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/ml-array-max/-/ml-array-max-2.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/ml-array-max/-/ml-array-max-2.0.0.tgz",
|
||||||
@@ -2425,6 +2511,12 @@
|
|||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/normalize-wheel-es": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/ohash": {
|
"node_modules/ohash": {
|
||||||
"version": "2.0.11",
|
"version": "2.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
|
||||||
@@ -2651,22 +2743,6 @@
|
|||||||
"integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==",
|
"integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/primevue": {
|
|
||||||
"version": "4.5.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/primevue/-/primevue-4.5.5.tgz",
|
|
||||||
"integrity": "sha512-Kv5REIewCdP806QaoU+4nBXfmpzOGFKkZ9qH4KsL6MjiAQVc4PUzypt8erl4r3Vzh3nr3aWZIxkxYRRsLGiX2A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@primeuix/styled": "^0.7.4",
|
|
||||||
"@primeuix/styles": "^2.0.3",
|
|
||||||
"@primeuix/utils": "^0.6.2",
|
|
||||||
"@primevue/core": "4.5.5",
|
|
||||||
"@primevue/icons": "4.5.5"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/punycode.js": {
|
"node_modules/punycode.js": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz",
|
"resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz",
|
||||||
@@ -3010,6 +3086,12 @@
|
|||||||
"vue": "^3.0.0-0 || ^2.7.0"
|
"vue": "^3.0.0-0 || ^2.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vue-component-type-helpers": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-l4Z2Y34m7nFMlx8vrslJaVtXxUpzgDMSESC7TakG/c5kwjYT/do+E0NcT2/vWDzaoIhsShg/2OKwX7Q4nbzC0g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/vue-router": {
|
"node_modules/vue-router": {
|
||||||
"version": "4.5.1",
|
"version": "4.5.1",
|
||||||
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz",
|
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz",
|
||||||
|
|||||||
@@ -11,14 +11,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/g6": "^5.1.1",
|
"@antv/g6": "^5.1.1",
|
||||||
"@primevue/themes": "^4.5.4",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"@vitejs/plugin-vue": "^5.2.4",
|
"@vitejs/plugin-vue": "^5.2.4",
|
||||||
"@vueuse/motion": "^3.0.3",
|
"@vueuse/motion": "^3.0.3",
|
||||||
"chart.js": "^4.5.1",
|
"chart.js": "^4.5.1",
|
||||||
|
"element-plus": "^2.14.0",
|
||||||
"markdown-it": "^14.1.1",
|
"markdown-it": "^14.1.1",
|
||||||
"pg": "^8.13.1",
|
"pg": "^8.13.1",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primevue": "^4.5.5",
|
|
||||||
"vite": "^5.4.19",
|
"vite": "^5.4.19",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-chartjs": "^5.3.3",
|
"vue-chartjs": "^5.3.3",
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="headerGradient" x1="12" y1="10" x2="54" y2="56" gradientUnits="userSpaceOnUse">
|
<linearGradient id="headerGradient" x1="12" y1="10" x2="54" y2="56" gradientUnits="userSpaceOnUse">
|
||||||
<stop stop-color="#34D399"/>
|
<stop stop-color="#6FA6C8"/>
|
||||||
<stop offset="1" stop-color="#059669"/>
|
<stop offset="1" stop-color="#3A7CA5"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
<circle cx="32" cy="32" r="32" fill="url(#headerGradient)"/>
|
<circle cx="32" cy="32" r="32" fill="url(#headerGradient)"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 742 B After Width: | Height: | Size: 742 B |
@@ -15,9 +15,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.app {
|
.app {
|
||||||
--sidebar-expanded-width: 220px;
|
--sidebar-expanded-width: 184px;
|
||||||
--sidebar-collapsed-width: 64px;
|
--sidebar-collapsed-width: 64px;
|
||||||
--sidebar-motion: 320ms cubic-bezier(0.22, 1, 0.36, 1);
|
--sidebar-motion: 220ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
|
||||||
height: var(--desktop-stage-height, 100dvh);
|
height: var(--desktop-stage-height, 100dvh);
|
||||||
min-height: var(--desktop-stage-height, 100dvh);
|
min-height: var(--desktop-stage-height, 100dvh);
|
||||||
@@ -27,18 +27,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.app-sidebar {
|
.app-sidebar {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 var(--sidebar-expanded-width);
|
||||||
width: var(--sidebar-expanded-width);
|
width: var(--sidebar-expanded-width);
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
overflow: hidden;
|
position: relative;
|
||||||
will-change: width;
|
overflow: visible;
|
||||||
transition: width var(--sidebar-motion);
|
z-index: 200;
|
||||||
|
will-change: width, flex-basis;
|
||||||
|
transition:
|
||||||
|
width var(--sidebar-motion),
|
||||||
|
flex-basis var(--sidebar-motion),
|
||||||
|
box-shadow 160ms var(--ease);
|
||||||
}
|
}
|
||||||
|
|
||||||
.app.sidebar-collapsed .app-sidebar {
|
.app.sidebar-collapsed .app-sidebar {
|
||||||
|
flex-basis: var(--sidebar-collapsed-width);
|
||||||
width: var(--sidebar-collapsed-width);
|
width: var(--sidebar-collapsed-width);
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
position: relative;
|
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +63,7 @@
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top left, rgba(16, 185, 129, 0.16), transparent 24rem),
|
radial-gradient(circle at top left, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.14), transparent 24rem),
|
||||||
radial-gradient(circle at bottom right, rgba(59, 130, 246, 0.14), transparent 28rem),
|
radial-gradient(circle at bottom right, rgba(59, 130, 246, 0.14), transparent 28rem),
|
||||||
#f8fafc;
|
#f8fafc;
|
||||||
}
|
}
|
||||||
@@ -89,9 +94,9 @@
|
|||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border-radius: 999px;
|
border-radius: 4px;
|
||||||
background: rgba(16, 185, 129, 0.12);
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 0.12em;
|
letter-spacing: 0.12em;
|
||||||
@@ -173,18 +178,30 @@
|
|||||||
}
|
}
|
||||||
@media (max-width: 760px) {
|
@media (max-width: 760px) {
|
||||||
.app {
|
.app {
|
||||||
display: block;
|
display: flex;
|
||||||
|
width: 100vw;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-sidebar {
|
.app-sidebar {
|
||||||
width: 100%;
|
width: var(--sidebar-collapsed-width);
|
||||||
|
flex: 0 0 var(--sidebar-collapsed-width);
|
||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app > .main {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
width: calc(100vw - var(--sidebar-collapsed-width));
|
||||||
|
}
|
||||||
|
|
||||||
.workarea { padding: 18px 16px 28px; }
|
.workarea { padding: 18px 16px 28px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.app-sidebar {
|
.app-sidebar {
|
||||||
transition: none;
|
transition:
|
||||||
|
width 120ms ease-out !important,
|
||||||
|
flex-basis 120ms ease-out !important;
|
||||||
|
transition-duration: 120ms, 120ms !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
.application-dialog-eyebrow {
|
.application-dialog-eyebrow {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -106,8 +106,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.application-input-panel textarea:focus {
|
.application-input-panel textarea:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.application-example-row {
|
.application-example-row {
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
.primary-parse-btn,
|
.primary-parse-btn,
|
||||||
.confirm-btn {
|
.confirm-btn {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: #059669;
|
background: var(--theme-gradient-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ontology-panel-head strong {
|
.ontology-panel-head strong {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ontology-empty-state {
|
.ontology-empty-state {
|
||||||
@@ -215,8 +215,8 @@
|
|||||||
|
|
||||||
.ontology-chip {
|
.ontology-chip {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #eefbf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
@@ -269,7 +269,7 @@
|
|||||||
|
|
||||||
.application-policy-strip i {
|
.application-policy-strip i {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
705
web/src/assets/styles/components/personal-workbench.css
Normal file
705
web/src/assets/styles/components/personal-workbench.css
Normal file
@@ -0,0 +1,705 @@
|
|||||||
|
.workbench {
|
||||||
|
min-width: 0;
|
||||||
|
display: grid;
|
||||||
|
gap: 16px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-hero {
|
||||||
|
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);
|
||||||
|
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%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-hero::before,
|
||||||
|
.assistant-hero::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.06);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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%);
|
||||||
|
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;
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-copy h3 {
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 26px;
|
||||||
|
line-height: 1.25;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-copy p {
|
||||||
|
max-width: 760px;
|
||||||
|
color: #5b6b83;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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-input textarea {
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1;
|
||||||
|
height: 22px;
|
||||||
|
min-height: 22px;
|
||||||
|
max-height: 22px;
|
||||||
|
resize: none;
|
||||||
|
border: 0;
|
||||||
|
padding: 1px 0;
|
||||||
|
background: transparent;
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 22px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-input textarea::placeholder {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-input 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 {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-file-strip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-file-note,
|
||||||
|
.assistant-file-chip {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 30px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-file-note {
|
||||||
|
background: var(--theme-primary-soft);
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.assistant-file-chip {
|
||||||
|
max-width: 220px;
|
||||||
|
overflow: hidden;
|
||||||
|
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;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ghost-action {
|
||||||
|
height: 40px;
|
||||||
|
display: inline-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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary-action {
|
||||||
|
height: 40px;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-panel,
|
||||||
|
.policy-panel {
|
||||||
|
padding: 20px 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-head h3 {
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-with-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-badge {
|
||||||
|
min-width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-action {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-body {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-row,
|
||||||
|
.progress-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 56px minmax(0, 1fr) auto;
|
||||||
|
gap: 14px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 14px 0;
|
||||||
|
border-top: 1px solid #edf2f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-row:first-child,
|
||||||
|
.progress-row:first-child {
|
||||||
|
padding-top: 4px;
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.policy-row strong {
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.policy-row span {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.policy-title-cell,
|
||||||
|
.policy-summary-cell {
|
||||||
|
justify-self: stretch;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.policy-date-cell {
|
||||||
|
justify-self: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1320px) {
|
||||||
|
.assistant-copy h3 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.policy-row {
|
||||||
|
grid-template-columns: 1.8fr 1.8fr 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
.risk-sim-message-row.user .risk-sim-bubble {
|
.risk-sim-message-row.user .risk-sim-bubble {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
background: #0f766e;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@
|
|||||||
border: 1px solid #dbe5ef;
|
border: 1px solid #dbe5ef;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-message-row.user .risk-sim-avatar {
|
.risk-sim-message-row.user .risk-sim-avatar {
|
||||||
@@ -483,8 +483,8 @@
|
|||||||
.risk-sim-recognized-fields em {
|
.risk-sim-recognized-fields em {
|
||||||
padding: 3px 7px;
|
padding: 3px 7px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
@@ -574,9 +574,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-file-chip.recognized {
|
.risk-sim-file-chip.recognized {
|
||||||
border-color: #bbf7d0;
|
border-color: var(--success-line);
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-file-chip.failed {
|
.risk-sim-file-chip.failed {
|
||||||
@@ -611,8 +611,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-send-btn {
|
.risk-sim-send-btn {
|
||||||
border-color: #0f766e;
|
border-color: var(--theme-primary);
|
||||||
background: #0f766e;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,8 +634,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-composer-shell:focus-within {
|
.risk-sim-composer-shell:focus-within {
|
||||||
border-color: rgba(15, 118, 110, 0.58);
|
border-color: rgba(var(--theme-primary-rgb), 0.58);
|
||||||
box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.1);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-composer-shell textarea {
|
.risk-sim-composer-shell textarea {
|
||||||
@@ -699,8 +699,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-step.done i {
|
.risk-sim-step.done i {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-step.running i {
|
.risk-sim-step.running i {
|
||||||
@@ -823,8 +823,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.risk-sim-primary-btn {
|
.risk-sim-primary-btn {
|
||||||
border: 1px solid #0f766e;
|
border: 1px solid var(--theme-primary);
|
||||||
background: #0f766e;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
533
web/src/assets/styles/components/sidebar-rail.css
Normal file
533
web/src/assets/styles/components/sidebar-rail.css
Normal file
@@ -0,0 +1,533 @@
|
|||||||
|
.rail {
|
||||||
|
--rail-motion-duration: 220ms;
|
||||||
|
--rail-motion-ease: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
--rail-fade-duration: 110ms;
|
||||||
|
--rail-label-delay: 55ms;
|
||||||
|
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: var(--desktop-stage-height, 100dvh);
|
||||||
|
min-height: var(--desktop-stage-height, 100dvh);
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: visible;
|
||||||
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.96)), #fff;
|
||||||
|
border-right: 1px solid #dbe4ee;
|
||||||
|
box-shadow: 1px 0 0 rgba(15, 23, 42, 0.02);
|
||||||
|
z-index: 20;
|
||||||
|
contain: layout;
|
||||||
|
transform: translateZ(0);
|
||||||
|
transition:
|
||||||
|
background 240ms var(--ease),
|
||||||
|
box-shadow 240ms var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-brand {
|
||||||
|
position: relative;
|
||||||
|
min-height: 112px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 54px 16px 8px;
|
||||||
|
overflow: visible;
|
||||||
|
transition:
|
||||||
|
min-height var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
gap var(--rail-motion-duration) var(--rail-motion-ease);
|
||||||
|
will-change: min-height, padding, gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-mark {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
transform: translateY(-8px);
|
||||||
|
transition:
|
||||||
|
color 160ms var(--ease),
|
||||||
|
transform var(--rail-motion-duration) var(--rail-motion-ease);
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-logo {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-mark svg {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
fill: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-name {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 124px;
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 800;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
transform: translateY(-8px);
|
||||||
|
transition:
|
||||||
|
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
opacity var(--rail-fade-duration) var(--rail-motion-ease) var(--rail-label-delay),
|
||||||
|
transform var(--rail-fade-duration) var(--rail-motion-ease) var(--rail-label-delay);
|
||||||
|
will-change: max-width, opacity, transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapse-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: -14px;
|
||||||
|
top: 55px;
|
||||||
|
z-index: 30;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
display: inline-grid;
|
||||||
|
place-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #dbe4ee;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(255, 255, 255, 0.96);
|
||||||
|
color: #64748b;
|
||||||
|
box-shadow:
|
||||||
|
0 8px 18px rgba(15, 23, 42, 0.12),
|
||||||
|
0 0 0 3px rgba(248, 250, 252, 0.92);
|
||||||
|
transition:
|
||||||
|
top var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
right var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
height var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
transform var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
background 180ms var(--ease),
|
||||||
|
border-color 180ms var(--ease),
|
||||||
|
color 180ms var(--ease),
|
||||||
|
box-shadow 180ms var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapse-btn:hover {
|
||||||
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.28);
|
||||||
|
background: #fff;
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
box-shadow:
|
||||||
|
0 10px 22px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.16),
|
||||||
|
0 0 0 3px rgba(248, 250, 252, 0.96);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapse-btn .mdi {
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 4px 8px 16px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
flex: 1;
|
||||||
|
transition:
|
||||||
|
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
gap var(--rail-motion-duration) var(--rail-motion-ease);
|
||||||
|
will-change: padding, gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 48px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: transparent;
|
||||||
|
color: #64748b;
|
||||||
|
text-align: left;
|
||||||
|
overflow: hidden;
|
||||||
|
transition:
|
||||||
|
gap var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
background 180ms var(--ease),
|
||||||
|
border-color 180ms var(--ease),
|
||||||
|
color 180ms var(--ease);
|
||||||
|
will-change: gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn:hover {
|
||||||
|
background: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn.active {
|
||||||
|
background: var(--theme-primary-soft);
|
||||||
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18);
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
flex: 0 0 48px;
|
||||||
|
width: 48px;
|
||||||
|
height: 36px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: currentColor;
|
||||||
|
transition: color 180ms var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn :deep(svg) {
|
||||||
|
width: 19px;
|
||||||
|
height: 19px;
|
||||||
|
stroke: currentColor;
|
||||||
|
stroke-width: 2;
|
||||||
|
fill: none;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-label {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 128px;
|
||||||
|
color: currentColor;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 1;
|
||||||
|
transition:
|
||||||
|
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
opacity var(--rail-fade-duration) var(--rail-motion-ease) var(--rail-label-delay),
|
||||||
|
transform var(--rail-fade-duration) var(--rail-motion-ease) var(--rail-label-delay);
|
||||||
|
will-change: max-width, opacity, transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-badge {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 34px;
|
||||||
|
height: 22px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #ff5b67;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
transition:
|
||||||
|
min-width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
opacity var(--rail-fade-duration) var(--rail-motion-ease) var(--rail-label-delay);
|
||||||
|
will-change: min-width, max-width, padding, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-unread-dot {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #ef4444;
|
||||||
|
box-shadow: 0 6px 14px rgba(239, 68, 68, 0.26);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-user {
|
||||||
|
position: relative;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 78px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 16px 20px 18px;
|
||||||
|
border-top: 1px solid #edf2f7;
|
||||||
|
transition: padding var(--rail-motion-duration) var(--rail-motion-ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-summary {
|
||||||
|
position: relative;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 42px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 4px;
|
||||||
|
color: #64748b;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition:
|
||||||
|
gap var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
background 180ms var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-user:hover .user-summary {
|
||||||
|
background: rgba(255, 255, 255, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-avatar {
|
||||||
|
flex: 0 0 36px;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
|
box-shadow: 0 6px 14px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 800;
|
||||||
|
transition:
|
||||||
|
flex-basis var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
height var(--rail-motion-duration) var(--rail-motion-ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-copy {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 116px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
opacity: 1;
|
||||||
|
transition:
|
||||||
|
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
opacity var(--rail-fade-duration) var(--rail-motion-ease) var(--rail-label-delay),
|
||||||
|
transform var(--rail-fade-duration) var(--rail-motion-ease) var(--rail-label-delay);
|
||||||
|
will-change: max-width, opacity, transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-copy strong {
|
||||||
|
color: #334155;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 750;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-copy span {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-summary .mdi {
|
||||||
|
flex: 0 0 18px;
|
||||||
|
font-size: 18px;
|
||||||
|
transition:
|
||||||
|
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
|
opacity var(--rail-fade-duration) var(--rail-motion-ease) var(--rail-label-delay);
|
||||||
|
will-change: max-width, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu {
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
bottom: calc(100% - 6px);
|
||||||
|
min-width: 132px;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid rgba(226, 232, 240, 0.96);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.98);
|
||||||
|
box-shadow: 0 16px 32px rgba(15, 23, 42, 0.1);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(8px);
|
||||||
|
pointer-events: none;
|
||||||
|
transition: all 180ms var(--ease);
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-user:hover .user-menu {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-menu-item {
|
||||||
|
width: 100%;
|
||||||
|
height: 38px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: transparent;
|
||||||
|
color: #dc2626;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
transition: all 180ms var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================= */
|
||||||
|
/* COLLAPSED STATE */
|
||||||
|
/* ========================================= */
|
||||||
|
|
||||||
|
.rail-collapsed .rail-brand {
|
||||||
|
min-height: 136px;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 0;
|
||||||
|
padding: 52px 16px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .brand-mark {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 0;
|
||||||
|
transform: translateY(-6px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .brand-mark svg {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .brand-name {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
max-width: 0;
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateX(-6px);
|
||||||
|
transition-delay: 0ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .rail-collapse-btn {
|
||||||
|
top: 96px;
|
||||||
|
right: -14px;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .rail-nav {
|
||||||
|
gap: 8px;
|
||||||
|
padding: 4px 8px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .nav-btn {
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 0;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .nav-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 36px;
|
||||||
|
flex: 0 0 48px;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .nav-label {
|
||||||
|
max-width: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-6px);
|
||||||
|
transition-delay: 0ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .nav-badge {
|
||||||
|
max-width: 0;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition-delay: 0ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .nav-unread-dot {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 11px;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .rail-user {
|
||||||
|
position: relative;
|
||||||
|
z-index: 6;
|
||||||
|
padding: 14px 8px;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .user-summary {
|
||||||
|
justify-content: center;
|
||||||
|
padding: 4px;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-user-menu-floating {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 12000;
|
||||||
|
min-width: 132px;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid rgba(226, 232, 240, 0.96);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.98);
|
||||||
|
box-shadow: 0 16px 32px rgba(15, 23, 42, 0.14);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
animation: railUserMenuIn 180ms var(--rail-motion-ease) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-user-menu-floating .user-menu-item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes railUserMenuIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-50%) translateX(-6px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-50%) translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .user-copy,
|
||||||
|
.rail-collapsed .user-summary .mdi {
|
||||||
|
max-width: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transform: translateX(-6px);
|
||||||
|
transition-delay: 0ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px) {
|
||||||
|
.rail {
|
||||||
|
position: relative;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.rail *,
|
||||||
|
.rail *::before,
|
||||||
|
.rail *::after {
|
||||||
|
transition-duration: 120ms !important;
|
||||||
|
animation-duration: 120ms !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
459
web/src/assets/styles/components/top-bar.css
Normal file
459
web/src/assets/styles/components/top-bar.css
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
.topbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 24px;
|
||||||
|
padding: 18px 24px 20px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar.chat-mode {
|
||||||
|
padding-bottom: 16px;
|
||||||
|
border-bottom: 1px solid #eef2f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-group {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eyebrow {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: linear-gradient(135deg, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.12), rgba(59, 130, 246, 0.08));
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 1.2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar h1 {
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar p {
|
||||||
|
margin-top: 6px;
|
||||||
|
max-width: 720px;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 14px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-combo {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-shell {
|
||||||
|
height: 42px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #d7e0ea;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-meta {
|
||||||
|
height: 34px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border-right: 1px solid #e2e8f0;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 650;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-meta .mdi {
|
||||||
|
color: var(--theme-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
padding-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs button {
|
||||||
|
height: 34px;
|
||||||
|
min-width: 54px;
|
||||||
|
padding: 0 14px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: transparent;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: background 160ms ease, color 160ms ease, box-shadow 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs button:hover:not(.active) {
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs button.active {
|
||||||
|
background: var(--theme-primary);
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 6px 14px rgba(var(--theme-primary-rgb, 58, 124, 165), .18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-range-wrap {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-range-btn {
|
||||||
|
height: 42px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 0 13px;
|
||||||
|
border: 1px solid #d7e0ea;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 750;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-range-btn:hover,
|
||||||
|
.custom-range-btn.active {
|
||||||
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), .34);
|
||||||
|
background: #f5fbff;
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-popover {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 10px);
|
||||||
|
right: 0;
|
||||||
|
width: 336px;
|
||||||
|
z-index: 40;
|
||||||
|
display: grid;
|
||||||
|
gap: 14px;
|
||||||
|
padding: 16px;
|
||||||
|
border: 1px solid #d7e0ea;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 18px 42px rgba(15, 23, 42, .16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-popover header,
|
||||||
|
.calendar-popover footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-popover header strong {
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-popover header button {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: transparent;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-fields {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-fields label {
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-fields span {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-fields input {
|
||||||
|
width: 100%;
|
||||||
|
height: 38px;
|
||||||
|
padding: 0 9px;
|
||||||
|
border: 1px solid #d7e0ea;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ghost-btn,
|
||||||
|
.apply-btn {
|
||||||
|
height: 36px;
|
||||||
|
padding: 0 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 750;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ghost-btn {
|
||||||
|
border: 1px solid #d7e0ea;
|
||||||
|
background: #fff;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apply-btn {
|
||||||
|
border: 0;
|
||||||
|
background: var(--theme-primary);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apply-btn:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
background: #cbd5e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-chips {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-alert-strip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-alert-pill {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border: 1px solid #fed7aa;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #fff7ed;
|
||||||
|
color: #ea580c;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-alert-pill i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-alert-pill.success {
|
||||||
|
border-color: var(--success-line);
|
||||||
|
background: var(--success-soft);
|
||||||
|
color: var(--success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-alert-pill.danger {
|
||||||
|
border-color: #fecaca;
|
||||||
|
background: #fff1f2;
|
||||||
|
color: #dc2626;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-chip {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
gap: 2px 10px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: linear-gradient(135deg, color-mix(in srgb, var(--chip-color) 8%, #fff), color-mix(in srgb, var(--chip-color) 3%, #f8fafc));
|
||||||
|
border: 1px solid color-mix(in srgb, var(--chip-color) 18%, #e2e8f0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-value {
|
||||||
|
grid-row: 1 / 3;
|
||||||
|
align-self: center;
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 850;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-value small {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-label {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-delta {
|
||||||
|
color: #94a3b8;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-delta.up { color: var(--success); }
|
||||||
|
.chip-delta.down { color: #f59e0b; }
|
||||||
|
|
||||||
|
.topbar-spacer {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-top-btn {
|
||||||
|
height: 40px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 0 18px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--theme-primary);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 750;
|
||||||
|
box-shadow: 0 8px 18px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-top-btn:hover {
|
||||||
|
background: var(--theme-primary-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1120px) {
|
||||||
|
.range-combo {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 960px) {
|
||||||
|
.topbar {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-actions,
|
||||||
|
.search-wrap,
|
||||||
|
.search-wrap.wide,
|
||||||
|
.detail-alert-strip,
|
||||||
|
.month-chip,
|
||||||
|
.qa-filter,
|
||||||
|
.new-question-btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-combo {
|
||||||
|
justify-content: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-shell {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-meta {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-range-btn {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-popover {
|
||||||
|
right: auto;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.topbar {
|
||||||
|
gap: 14px;
|
||||||
|
padding: 16px 16px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-chips {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-chip {
|
||||||
|
min-width: 118px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-label,
|
||||||
|
.chip-delta {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-combo {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-shell {
|
||||||
|
height: auto;
|
||||||
|
display: grid;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-meta {
|
||||||
|
width: 100%;
|
||||||
|
border-right: 0;
|
||||||
|
border-bottom: 1px solid #e2e8f0;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs {
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-popover {
|
||||||
|
width: min(336px, calc(100vw - 32px));
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-fields {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,381 @@
|
|||||||
|
.insight-panel-shell {
|
||||||
|
flex: none;
|
||||||
|
display: flex;
|
||||||
|
width: clamp(300px, 28vw, 420px);
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: width 360ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.insight-panel-shell.collapsed {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.insight-panel {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto minmax(0, 1fr);
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid rgba(189, 201, 214, 0.74);
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0 14px 32px rgba(148, 163, 184, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.insight-head {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
border-bottom: 1px solid #e2e8f0;
|
||||||
|
background: linear-gradient(180deg, #f8fbff, #ffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.insight-head h3 {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: var(--wb-fs-insight-title, 17px);
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.insight-head p {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: var(--wb-fs-insight-body, 12px);
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.insight-body {
|
||||||
|
min-height: 0;
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
align-content: start;
|
||||||
|
padding: 14px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intent-pill,
|
||||||
|
.flow-status-chip,
|
||||||
|
.status-pill {
|
||||||
|
min-height: 26px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confidence-card,
|
||||||
|
.insight-card,
|
||||||
|
.review-side-card,
|
||||||
|
.review-flow-panel {
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confidence-card {
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
background: #f8fbff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confidence-card span,
|
||||||
|
.card-head p,
|
||||||
|
.note-block p,
|
||||||
|
.review-side-head p,
|
||||||
|
.review-side-risk-summary,
|
||||||
|
.flow-step-tool,
|
||||||
|
.flow-step-detail,
|
||||||
|
.flow-step-card time {
|
||||||
|
margin: 0;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: var(--wb-fs-insight-body, 12px);
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confidence-card strong,
|
||||||
|
.card-head h4,
|
||||||
|
.note-block strong,
|
||||||
|
.review-side-head strong,
|
||||||
|
.flow-step-card strong,
|
||||||
|
.review-side-metric-copy strong,
|
||||||
|
.review-side-category-copy strong {
|
||||||
|
color: #0f172a;
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-head,
|
||||||
|
.review-side-head,
|
||||||
|
.flow-step-card header,
|
||||||
|
.review-document-switch-head,
|
||||||
|
.review-flow-summary {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-head h4 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--wb-fs-insight-h4, 14px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-block {
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #f8fbff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.capability-chip-row,
|
||||||
|
.citation-stack,
|
||||||
|
.knowledge-question-list,
|
||||||
|
.review-flow-list,
|
||||||
|
.review-side-risk-list,
|
||||||
|
.review-document-warning-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.risk-chip,
|
||||||
|
.review-document-meta-chip,
|
||||||
|
.review-side-confidence {
|
||||||
|
min-height: 24px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.citation-card,
|
||||||
|
.knowledge-question-btn,
|
||||||
|
.review-side-metric-card,
|
||||||
|
.review-side-category-card,
|
||||||
|
.review-side-risk-item,
|
||||||
|
.flow-step-card,
|
||||||
|
.review-document-preview-card {
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.knowledge-question-btn,
|
||||||
|
.review-side-metric-card,
|
||||||
|
.review-side-category-card,
|
||||||
|
.review-side-risk-item {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
color: #334155;
|
||||||
|
font: inherit;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.knowledge-question-btn {
|
||||||
|
grid-template-columns: 30px minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.knowledge-question-index {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-side-grid,
|
||||||
|
.review-side-category-grid,
|
||||||
|
.review-document-edit-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-side-metric-card {
|
||||||
|
grid-template-columns: 30px minmax(0, 1fr) auto;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-side-metric-icon,
|
||||||
|
.review-side-risk-icon {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: var(--theme-primary, #3a7ca5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-side-metric-copy,
|
||||||
|
.review-side-category-copy,
|
||||||
|
.review-side-risk-copy {
|
||||||
|
display: grid;
|
||||||
|
gap: 4px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-side-metric-copy small,
|
||||||
|
.review-side-edit-hint,
|
||||||
|
.review-side-category-copy p {
|
||||||
|
margin: 0;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-side-category-card.active {
|
||||||
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.55);
|
||||||
|
background: var(--theme-primary-soft, #eaf4fa);
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-insight-tools,
|
||||||
|
.review-document-nav,
|
||||||
|
.review-document-meta-chip-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-insight-switch-icon-btn,
|
||||||
|
.flow-icon-btn,
|
||||||
|
.review-document-nav-btn,
|
||||||
|
.review-side-save-pill {
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-insight-switch-icon-btn,
|
||||||
|
.flow-icon-btn,
|
||||||
|
.review-document-nav-btn {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-insight-switch-icon-btn.active,
|
||||||
|
.review-side-save-pill {
|
||||||
|
border-color: var(--theme-primary, #3a7ca5);
|
||||||
|
background: var(--theme-primary, #3a7ca5);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-flow-list {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flow-step-item {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 28px minmax(0, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flow-step-rail span {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flow-step-card {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flow-empty-state,
|
||||||
|
.review-side-empty,
|
||||||
|
.review-document-preview-placeholder {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 18px;
|
||||||
|
border: 1px dashed #cbd5e1;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #f8fbff;
|
||||||
|
color: #64748b;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-inline-input,
|
||||||
|
.review-document-edit-field input,
|
||||||
|
.review-document-edit-field textarea {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 34px;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #0f172a;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-document-edit-field {
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-document-edit-field span {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-document-scroll {
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-document-preview-card {
|
||||||
|
min-height: 140px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f8fbff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-document-preview-card img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 240px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-side-save-pill {
|
||||||
|
min-height: 34px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1440px) {
|
||||||
|
.insight-panel-shell:not(.collapsed) {
|
||||||
|
width: 100%;
|
||||||
|
max-height: min(34dvh, 360px);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,469 @@
|
|||||||
|
.message-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 38px minmax(0, 1fr);
|
||||||
|
align-items: start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-row.user {
|
||||||
|
grid-template-columns: minmax(0, 1fr) 38px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-row.user .message-avatar {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-row.user .message-bubble {
|
||||||
|
order: 1;
|
||||||
|
justify-self: end;
|
||||||
|
background: linear-gradient(135deg, #eaf3ff, #f7fbff);
|
||||||
|
border-color: rgba(96, 165, 250, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-avatar {
|
||||||
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 999px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #eff6ff;
|
||||||
|
box-shadow: 0 8px 18px rgba(148, 163, 184, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-avatar img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble {
|
||||||
|
max-width: min(100%, 760px);
|
||||||
|
padding: 12px 14px;
|
||||||
|
border: 1px solid #d8e4f0;
|
||||||
|
border-radius: 14px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #24324a;
|
||||||
|
font-size: var(--wb-fs-bubble, 13px);
|
||||||
|
line-height: 1.62;
|
||||||
|
box-shadow: 0 10px 22px rgba(148, 163, 184, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble-application-preview {
|
||||||
|
max-width: min(100%, 980px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble-review-risk-low,
|
||||||
|
.message-bubble-review-risk-medium,
|
||||||
|
.message-bubble-review-risk-high {
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble-review-risk-low {
|
||||||
|
border-color: rgba(37, 99, 235, 0.56);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble-review-risk-medium {
|
||||||
|
border-color: rgba(217, 119, 6, 0.58);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble-review-risk-high {
|
||||||
|
border-color: rgba(220, 38, 38, 0.58);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-meta {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-meta strong {
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: var(--wb-fs-bubble-meta, 12px);
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-meta time {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: var(--wb-fs-bubble-time, 11px);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-answer-content {
|
||||||
|
color: #24324a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-answer-markdown :deep(p),
|
||||||
|
.message-answer-markdown :deep(li),
|
||||||
|
.message-answer-markdown :deep(td),
|
||||||
|
.message-answer-markdown :deep(th),
|
||||||
|
.message-answer-markdown :deep(blockquote) {
|
||||||
|
margin: 0;
|
||||||
|
color: inherit;
|
||||||
|
line-height: 1.62;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-answer-markdown :deep(p + p),
|
||||||
|
.message-answer-markdown :deep(p + ul),
|
||||||
|
.message-answer-markdown :deep(ul + p),
|
||||||
|
.message-answer-markdown :deep(ol + p) {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-answer-markdown :deep(strong) {
|
||||||
|
color: #0f172a;
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-quick-actions {
|
||||||
|
margin-top: 14px;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-quick-actions-title {
|
||||||
|
margin: 0 0 12px;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: var(--wb-fs-chip, 12px);
|
||||||
|
font-weight: 750;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-quick-action-grid,
|
||||||
|
.message-suggested-actions,
|
||||||
|
.message-detail-chip-row,
|
||||||
|
.message-files {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-quick-action-btn,
|
||||||
|
.message-suggested-action-btn,
|
||||||
|
.review-footer-btn,
|
||||||
|
.expense-query-record-card,
|
||||||
|
.expense-query-risk-chip {
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #334155;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-quick-action-btn,
|
||||||
|
.review-footer-btn {
|
||||||
|
min-height: 32px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: var(--wb-fs-chip, 12px);
|
||||||
|
font-weight: 750;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-quick-action-btn i {
|
||||||
|
color: var(--theme-primary, #3a7ca5);
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-quick-action-btn:hover:not(:disabled),
|
||||||
|
.message-suggested-action-btn:hover:not(:disabled),
|
||||||
|
.review-footer-btn:hover:not(:disabled) {
|
||||||
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.55);
|
||||||
|
background: var(--theme-primary-soft, #eaf4fa);
|
||||||
|
color: var(--theme-primary-active, #2f6d95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-meta-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-meta-chip,
|
||||||
|
.message-risk-chip,
|
||||||
|
.file-chip {
|
||||||
|
min-height: 26px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 0 9px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 750;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-suggested-actions {
|
||||||
|
margin-top: 12px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-suggested-action-btn {
|
||||||
|
min-height: 54px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 30px minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-suggested-action-icon {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: var(--theme-primary, #3a7ca5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-suggested-action-copy {
|
||||||
|
display: grid;
|
||||||
|
gap: 3px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-suggested-action-title {
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-suggested-action-btn small {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-detail-block,
|
||||||
|
.application-preview-table,
|
||||||
|
.draft-preview {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #f8fbff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-detail-block > strong,
|
||||||
|
.expense-query-block > strong {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-table {
|
||||||
|
display: grid;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(96px, 0.42fr) minmax(0, 1fr);
|
||||||
|
min-height: 38px;
|
||||||
|
border-top: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-row:first-child {
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-row.head {
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-row > span {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-label {
|
||||||
|
color: #64748b;
|
||||||
|
border-right: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-value {
|
||||||
|
color: #0f172a;
|
||||||
|
font-weight: 750;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-input {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 32px;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-preview-edit-btn {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
display: inline-grid;
|
||||||
|
place-items: center;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #2563eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-query-record-list,
|
||||||
|
.message-citation-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-query-record-card {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-query-record-main {
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-query-record-top,
|
||||||
|
.expense-query-record-meta,
|
||||||
|
.expense-query-summary-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-query-record-top strong {
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-query-record-card p,
|
||||||
|
.expense-query-record-meta span,
|
||||||
|
.expense-query-window-label,
|
||||||
|
.expense-query-hint {
|
||||||
|
margin: 0;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-query-record-status,
|
||||||
|
.expense-query-summary-chip {
|
||||||
|
min-height: 22px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-query-empty {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-plain-followup,
|
||||||
|
.draft-preview {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-plain-lead {
|
||||||
|
margin: 0;
|
||||||
|
color: #0f172a;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 850;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-plain-summary,
|
||||||
|
.review-plain-note {
|
||||||
|
margin: 0;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-plain-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 18px;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-footer-actions {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-footer-btn.primary {
|
||||||
|
border-color: var(--theme-primary, #3a7ca5);
|
||||||
|
background: var(--theme-primary, #3a7ca5);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.draft-preview header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.draft-preview pre {
|
||||||
|
margin: 0;
|
||||||
|
overflow: auto;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px) {
|
||||||
|
.message-row,
|
||||||
|
.message-row.user {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-avatar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-row.user .message-bubble {
|
||||||
|
justify-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble {
|
||||||
|
max-width: 100%;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
131
web/src/assets/styles/element-plus-theme.css
Normal file
131
web/src/assets/styles/element-plus-theme.css
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
:root {
|
||||||
|
--theme-primary: #3a7ca5;
|
||||||
|
--theme-primary-hover: #2f6d95;
|
||||||
|
--theme-primary-active: #255b7d;
|
||||||
|
--theme-primary-soft: #eaf4fa;
|
||||||
|
--theme-primary-soft-strong: #d4e8f3;
|
||||||
|
--theme-primary-rgb: 58, 124, 165;
|
||||||
|
--theme-focus-ring: rgba(58, 124, 165, 0.12);
|
||||||
|
--el-color-primary: var(--theme-primary);
|
||||||
|
--el-color-primary-light-3: var(--theme-primary-hover);
|
||||||
|
--el-color-primary-light-5: var(--theme-primary-light-5);
|
||||||
|
--el-color-primary-light-7: var(--theme-primary-soft-strong);
|
||||||
|
--el-color-primary-light-8: var(--theme-primary-soft);
|
||||||
|
--el-color-primary-light-9: var(--theme-primary-light-9);
|
||||||
|
--el-color-primary-dark-2: var(--theme-primary-active);
|
||||||
|
--el-color-success: var(--success);
|
||||||
|
--el-color-success-light-9: var(--success-soft);
|
||||||
|
--el-color-warning: var(--warning);
|
||||||
|
--el-color-warning-light-9: var(--warning-soft);
|
||||||
|
--el-color-danger: var(--danger);
|
||||||
|
--el-color-danger-light-9: var(--danger-soft);
|
||||||
|
--el-color-info: var(--info);
|
||||||
|
--el-border-radius-base: 4px;
|
||||||
|
--el-border-radius-small: 3px;
|
||||||
|
--el-border-radius-round: 4px;
|
||||||
|
--el-border-color: var(--line-strong);
|
||||||
|
--el-border-color-light: var(--line);
|
||||||
|
--el-border-color-lighter: #edf2f7;
|
||||||
|
--el-fill-color-light: var(--bg);
|
||||||
|
--el-fill-color-lighter: var(--surface-soft);
|
||||||
|
--el-fill-color-blank: var(--surface);
|
||||||
|
--el-text-color-primary: var(--ink);
|
||||||
|
--el-text-color-regular: var(--text);
|
||||||
|
--el-text-color-secondary: var(--muted);
|
||||||
|
--el-font-family: Inter, "SF Pro Text", "Segoe UI", "Microsoft YaHei", "PingFang SC", sans-serif;
|
||||||
|
--el-font-size-base: 14px;
|
||||||
|
--el-box-shadow-light: 0 8px 22px rgba(15, 23, 42, 0.08);
|
||||||
|
--el-box-shadow-lighter: 0 4px 14px rgba(15, 23, 42, 0.06);
|
||||||
|
--el-transition-duration: 180ms;
|
||||||
|
--el-transition-function-ease-in-out-bezier: cubic-bezier(0.2, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button,
|
||||||
|
.el-input__wrapper,
|
||||||
|
.el-select__wrapper,
|
||||||
|
.el-textarea__inner,
|
||||||
|
.el-date-editor.el-input__wrapper,
|
||||||
|
.el-popover.el-popper,
|
||||||
|
.el-popper.is-light,
|
||||||
|
.el-message-box,
|
||||||
|
.el-dialog {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__wrapper,
|
||||||
|
.el-select__wrapper {
|
||||||
|
min-height: 34px;
|
||||||
|
box-shadow: 0 0 0 1px var(--el-border-color) inset;
|
||||||
|
transition:
|
||||||
|
box-shadow 160ms var(--ease),
|
||||||
|
background-color 160ms var(--ease),
|
||||||
|
border-color 160ms var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__wrapper:hover,
|
||||||
|
.el-select__wrapper:hover {
|
||||||
|
box-shadow: 0 0 0 1px #b8c2d2 inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__wrapper.is-focus,
|
||||||
|
.el-select__wrapper.is-focused {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px var(--el-color-primary) inset,
|
||||||
|
0 0 0 3px var(--theme-focus-ring);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select-dropdown,
|
||||||
|
.el-picker__popper,
|
||||||
|
.el-dropdown__popper,
|
||||||
|
.el-popover.el-popper {
|
||||||
|
border: 1px solid rgba(148, 163, 184, 0.26);
|
||||||
|
box-shadow: 0 16px 36px rgba(15, 23, 42, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select-dropdown__item {
|
||||||
|
height: 34px;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select-dropdown__item.is-hovering {
|
||||||
|
background: #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select-dropdown__item.is-selected {
|
||||||
|
background: var(--theme-primary-soft);
|
||||||
|
color: var(--theme-primary-active);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-scrollbar__bar {
|
||||||
|
opacity: 0.28;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-overlay {
|
||||||
|
background-color: rgba(15, 23, 42, 0.42);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog,
|
||||||
|
.el-message-box {
|
||||||
|
box-shadow: 0 24px 70px rgba(15, 23, 42, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table {
|
||||||
|
--el-table-header-bg-color: #f8fafc;
|
||||||
|
--el-table-header-text-color: #334155;
|
||||||
|
--el-table-row-hover-bg-color: #f8fafc;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination {
|
||||||
|
--el-pagination-button-bg-color: #ffffff;
|
||||||
|
--el-pagination-hover-color: var(--theme-primary-active);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
@@ -7,21 +7,64 @@
|
|||||||
--muted: #64748b;
|
--muted: #64748b;
|
||||||
--line: #e2e8f0;
|
--line: #e2e8f0;
|
||||||
--line-strong: #cbd5e1;
|
--line-strong: #cbd5e1;
|
||||||
--primary: #10b981;
|
--primary: #3a7ca5;
|
||||||
--primary-soft: #ecfdf5;
|
--primary-hover: #2f6d95;
|
||||||
--secondary: #3b82f6;
|
--primary-active: #255b7d;
|
||||||
|
--primary-soft: #eaf4fa;
|
||||||
|
--primary-soft-strong: #d4e8f3;
|
||||||
|
--primary-rgb: 58, 124, 165;
|
||||||
|
--secondary: #4f6f9f;
|
||||||
|
--secondary-rgb: 79, 111, 159;
|
||||||
|
--theme-primary: var(--primary);
|
||||||
|
--theme-primary-hover: var(--primary-hover);
|
||||||
|
--theme-primary-active: var(--primary-active);
|
||||||
|
--theme-primary-soft: var(--primary-soft);
|
||||||
|
--theme-primary-soft-strong: var(--primary-soft-strong);
|
||||||
|
--theme-primary-light-5: color-mix(in srgb, var(--theme-primary) 52%, white);
|
||||||
|
--theme-primary-light-9: color-mix(in srgb, var(--theme-primary) 8%, white);
|
||||||
|
--theme-primary-contrast: #ffffff;
|
||||||
|
--theme-primary-shadow: rgba(var(--theme-primary-rgb), 0.16);
|
||||||
|
--theme-gradient-primary: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
|
--theme-primary-rgb: var(--primary-rgb);
|
||||||
|
--theme-secondary: var(--secondary);
|
||||||
|
--theme-secondary-rgb: var(--secondary-rgb);
|
||||||
|
--theme-focus-ring: rgba(var(--theme-primary-rgb), 0.12);
|
||||||
--purple: #8b5cf6;
|
--purple: #8b5cf6;
|
||||||
--orange: #f59e0b;
|
--orange: #f59e0b;
|
||||||
--red: #ef4444;
|
--red: #ef4444;
|
||||||
--success: #10b981;
|
--success: #2f855a;
|
||||||
--success-soft: #ecfdf5;
|
--success-hover: #276749;
|
||||||
--warning: #f59e0b;
|
--success-active: #22543d;
|
||||||
--warning-soft: #fffbeb;
|
--success-soft: #f0f7f2;
|
||||||
|
--success-line: #cde6d5;
|
||||||
|
--success-rgb: 47, 133, 90;
|
||||||
|
--warning: #b7791f;
|
||||||
|
--warning-hover: #975a16;
|
||||||
|
--warning-active: #7b4514;
|
||||||
|
--warning-soft: #fff8eb;
|
||||||
|
--warning-line: #efd9af;
|
||||||
|
--warning-rgb: 183, 121, 31;
|
||||||
--danger: #ef4444;
|
--danger: #ef4444;
|
||||||
|
--danger-hover: #dc2626;
|
||||||
|
--danger-active: #b91c1c;
|
||||||
--danger-soft: #fef2f2;
|
--danger-soft: #fef2f2;
|
||||||
|
--danger-line: #fecaca;
|
||||||
|
--danger-rgb: 239, 68, 68;
|
||||||
|
--info: #475569;
|
||||||
|
--info-hover: #334155;
|
||||||
|
--info-active: #1e293b;
|
||||||
|
--info-soft: #f1f5f9;
|
||||||
|
--info-line: #cbd5e1;
|
||||||
|
--info-rgb: 71, 85, 105;
|
||||||
|
--chart-primary: var(--theme-primary);
|
||||||
|
--chart-primary-rgb: var(--theme-primary-rgb);
|
||||||
|
--chart-blue: #4f6f9f;
|
||||||
|
--chart-purple: #6e7fa6;
|
||||||
|
--chart-amber: #b58b4c;
|
||||||
|
--chart-danger: var(--danger);
|
||||||
--nav: #0b1220;
|
--nav: #0b1220;
|
||||||
--nav-muted: #7d89a5;
|
--nav-muted: #7d89a5;
|
||||||
--radius: 8px;
|
--radius: 4px;
|
||||||
--ease: cubic-bezier(.2, .8, .2, 1);
|
--ease: cubic-bezier(.2, .8, .2, 1);
|
||||||
--desktop-ui-scale: 1;
|
--desktop-ui-scale: 1;
|
||||||
--desktop-ui-inverse-scale: 1;
|
--desktop-ui-inverse-scale: 1;
|
||||||
@@ -38,7 +81,7 @@ body { margin: 0; min-height: 100dvh; color: var(--text); background: var(--bg);
|
|||||||
.mdi { line-height: 1; vertical-align: middle; }
|
.mdi { line-height: 1; vertical-align: middle; }
|
||||||
button, input, select, textarea { font: inherit; }
|
button, input, select, textarea { font: inherit; }
|
||||||
button { cursor: pointer; }
|
button { cursor: pointer; }
|
||||||
button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 3px solid rgba(16,185,129,.20); outline-offset: 2px; }
|
button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 3px solid var(--theme-focus-ring, rgba(58,124,165,.18)); outline-offset: 2px; }
|
||||||
|
|
||||||
.eyebrow { color: var(--primary); font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
|
.eyebrow { color: var(--primary); font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
|
||||||
h1, h2, h3, p { margin: 0; }
|
h1, h2, h3, p { margin: 0; }
|
||||||
@@ -60,7 +103,7 @@ h1 { margin-top: 4px; color: var(--ink); font-size: 24px; line-height: 1.25; fon
|
|||||||
}
|
}
|
||||||
.btn:hover { transform: translateY(-1px); box-shadow: 0 10px 24px rgba(16,24,40,.08); }
|
.btn:hover { transform: translateY(-1px); box-shadow: 0 10px 24px rgba(16,24,40,.08); }
|
||||||
.btn:active, .mini-btn:active, .chip:active, .nav-btn:active { transform: scale(.97); }
|
.btn:active, .mini-btn:active, .chip:active, .nav-btn:active { transform: scale(.97); }
|
||||||
.btn.primary { border-color: transparent; background: var(--primary); color: #fff; box-shadow: 0 12px 24px rgba(51,92,255,.22); }
|
.btn.primary { border-color: transparent; background: var(--theme-primary); color: #fff; box-shadow: 0 10px 20px rgba(var(--theme-primary-rgb, 58, 124, 165), .18); }
|
||||||
.btn.success { border-color: transparent; background: var(--success); color: #fff; }
|
.btn.success { border-color: transparent; background: var(--success); color: #fff; }
|
||||||
.btn.danger { border-color: rgba(180,35,24,.18); background: var(--danger-soft); color: var(--danger); }
|
.btn.danger { border-color: rgba(180,35,24,.18); background: var(--danger-soft); color: var(--danger); }
|
||||||
.btn.ghost { background: transparent; }
|
.btn.ghost { background: transparent; }
|
||||||
@@ -110,13 +153,13 @@ h1 { margin-top: 4px; color: var(--ink); font-size: 24px; line-height: 1.25; fon
|
|||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 3px solid #e2e8f0;
|
border: 3px solid #e2e8f0;
|
||||||
border-top-color: #10b981;
|
border-top-color: var(--primary);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: table-spinner-rotate .8s linear infinite !important;
|
animation: table-spinner-rotate .8s linear infinite !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-loading.sky .table-loading__spinner {
|
.table-loading.sky .table-loading__spinner {
|
||||||
border-top-color: #0ea5e9;
|
border-top-color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-loading.detail .table-loading__spinner {
|
.table-loading.detail .table-loading__spinner {
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.opinion-wrap textarea:focus {
|
.opinion-wrap textarea:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, .12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,8 +55,8 @@
|
|||||||
.risk-total span { font-weight: 750; }
|
.risk-total span { font-weight: 750; }
|
||||||
|
|
||||||
.risk-total.high {
|
.risk-total.high {
|
||||||
background: #fee2e2;
|
background: var(--danger-soft);
|
||||||
color: #dc2626;
|
color: var(--danger-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-total.high strong { font-size: 16px; font-weight: 900; }
|
.risk-total.high strong { font-size: 16px; font-weight: 900; }
|
||||||
@@ -87,8 +87,8 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-row.high .risk-icon { background: #fef2f2; color: #ef4444; }
|
.risk-row.high .risk-icon { background: var(--danger-soft); color: var(--danger); }
|
||||||
.risk-row.medium .risk-icon { background: #fff7ed; color: #f97316; }
|
.risk-row.medium .risk-icon { background: var(--warning-soft); color: var(--warning-active); }
|
||||||
|
|
||||||
.risk-text {
|
.risk-text {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -105,8 +105,8 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-level.high { background: #fef2f2; color: #ef4444; }
|
.risk-level.high { background: var(--danger-soft); color: var(--danger); }
|
||||||
.risk-level.medium { background: #fff7ed; color: #f97316; }
|
.risk-level.medium { background: var(--warning-soft); color: var(--warning-active); }
|
||||||
|
|
||||||
/* ── Side Dual ── */
|
/* ── Side Dual ── */
|
||||||
.side-dual {
|
.side-dual {
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
|
|
||||||
.reminder-list li i {
|
.reminder-list li i {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
color: #f59e0b;
|
color: var(--warning);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
@@ -195,35 +195,35 @@
|
|||||||
|
|
||||||
.action-btn.supplement {
|
.action-btn.supplement {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-color: #fed7aa;
|
border-color: var(--warning-line);
|
||||||
color: #ea580c;
|
color: var(--warning-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.supplement:hover {
|
.action-btn.supplement:hover {
|
||||||
background: #fff7ed;
|
background: var(--warning-soft);
|
||||||
box-shadow: 0 4px 12px rgba(234, 88, 12, .12);
|
box-shadow: 0 4px 12px rgba(var(--warning-rgb), .12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.reject {
|
.action-btn.reject {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-color: #fecaca;
|
border-color: var(--danger-line);
|
||||||
color: #ef4444;
|
color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.reject:hover {
|
.action-btn.reject:hover {
|
||||||
background: #fef2f2;
|
background: var(--danger-soft);
|
||||||
box-shadow: 0 4px 12px rgba(239, 68, 68, .12);
|
box-shadow: 0 4px 12px rgba(var(--danger-rgb), .12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.approve {
|
.action-btn.approve {
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 4px 16px rgba(5, 150, 105, .25);
|
box-shadow: 0 4px 16px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.approve:hover {
|
.action-btn.approve:hover {
|
||||||
background: #047857;
|
background: var(--theme-primary-active);
|
||||||
box-shadow: 0 8px 24px rgba(5, 150, 105, .30);
|
box-shadow: 0 8px 24px rgba(var(--theme-primary-rgb), .30);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn:active { transform: scale(.97); }
|
.action-btn:active { transform: scale(.97); }
|
||||||
|
|||||||
@@ -34,15 +34,15 @@
|
|||||||
font-weight: 750;
|
font-weight: 750;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active { color: #059669; }
|
.status-tabs button.active { color: var(--theme-primary-active); }
|
||||||
|
|
||||||
.status-tabs button.active::after {
|
.status-tabs button.active::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0; right: 0; bottom: -1px;
|
left: 0; right: 0; bottom: -1px;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
border-radius: 999px 999px 0 0;
|
border-radius: 2px 2px 0 0;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-toolbar {
|
.list-toolbar {
|
||||||
@@ -86,8 +86,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.list-search input:focus {
|
.list-search input:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.14);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter-btn { min-width: 104px; justify-content: space-between; }
|
.filter-btn { min-width: 104px; justify-content: space-between; }
|
||||||
.filter-btn:hover, .page-size:hover { border-color: rgba(16, 185, 129, .32); color: #0f9f78; }
|
.filter-btn:hover, .page-size:hover { border-color: rgba(var(--theme-primary-rgb), .32); color: var(--theme-primary-active); }
|
||||||
|
|
||||||
.hint { display: inline-flex; align-items: center; gap: 7px; margin-top: 10px; color: #64748b; font-size: 13px; }
|
.hint { display: inline-flex; align-items: center; gap: 7px; margin-top: 10px; color: #64748b; font-size: 13px; }
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border: 1px solid #edf2f7;
|
border: 1px solid #edf2f7;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: linear-gradient(180deg, #fcfefd 0%, #f4f8f6 100%);
|
background: linear-gradient(180deg, #fcfeff 0%, #f4f8fc 100%);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
@@ -145,13 +145,13 @@
|
|||||||
padding: 28px 20px;
|
padding: 28px 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
background: linear-gradient(180deg, #fcfffd 0%, #f5f9f7 100%);
|
background: linear-gradient(180deg, #fcfeff 0%, #f5f9fc 100%);
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-state .mdi {
|
.table-state .mdi {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-state strong {
|
.table-state strong {
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.table-state.error .mdi {
|
.table-state.error .mdi {
|
||||||
color: #ef4444;
|
color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-action {
|
.state-action {
|
||||||
@@ -176,10 +176,10 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.28);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.28);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 760;
|
font-weight: 760;
|
||||||
}
|
}
|
||||||
@@ -207,11 +207,11 @@ th {
|
|||||||
|
|
||||||
tbody tr { cursor: pointer; }
|
tbody tr { cursor: pointer; }
|
||||||
tbody tr:hover, tbody tr.spotlight {
|
tbody tr:hover, tbody tr.spotlight {
|
||||||
background: linear-gradient(90deg, rgba(16, 185, 129, .08), rgba(16, 185, 129, .03));
|
background: linear-gradient(90deg, rgba(var(--theme-primary-rgb), .08), rgba(var(--theme-primary-rgb), .03));
|
||||||
}
|
}
|
||||||
tbody tr:last-child td { border-bottom: 0; }
|
tbody tr:last-child td { border-bottom: 0; }
|
||||||
|
|
||||||
.doc-id { color: #1d4ed8; font-weight: 800; }
|
.doc-id { color: var(--theme-primary-active); font-weight: 800; }
|
||||||
|
|
||||||
.person { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
|
.person { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
width: 24px; height: 24px;
|
width: 24px; height: 24px;
|
||||||
display: grid; place-items: center;
|
display: grid; place-items: center;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #dbeafe; color: #1d4ed8;
|
background: var(--theme-primary-soft); color: var(--theme-primary-active);
|
||||||
font-size: 12px; font-weight: 900;
|
font-size: 12px; font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,26 +231,26 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
font-size: 12px; font-weight: 750; white-space: nowrap;
|
font-size: 12px; font-weight: 750; white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-tag.low { background: #dcfce7; color: #059669; }
|
.risk-tag.low { background: var(--success-soft); color: var(--success); }
|
||||||
.risk-tag.medium { background: #ffedd5; color: #f97316; }
|
.risk-tag.medium { background: var(--warning-soft); color: var(--warning-active); }
|
||||||
.risk-tag.high { background: #fee2e2; color: #ef4444; }
|
.risk-tag.high { background: var(--danger-soft); color: var(--danger); }
|
||||||
|
|
||||||
.sla { font-size: 13px; font-weight: 850; }
|
.sla { font-size: 13px; font-weight: 850; }
|
||||||
.sla.safe { color: #059669; }
|
.sla.safe { color: var(--success); }
|
||||||
.sla.warning { color: #f97316; }
|
.sla.warning { color: var(--warning-active); }
|
||||||
.sla.danger { color: #ef4444; }
|
.sla.danger { color: var(--danger); }
|
||||||
|
|
||||||
.status-tag.pending { background: #eff6ff; color: #2563eb; }
|
.status-tag.pending { background: var(--theme-primary-soft); color: var(--theme-primary-active); }
|
||||||
.status-tag.urgent { background: #fff7ed; color: #f97316; }
|
.status-tag.urgent { background: var(--warning-soft); color: var(--warning-active); }
|
||||||
.status-tag.done { background: #ecfdf5; color: #059669; }
|
.status-tag.done { background: var(--success-soft); color: var(--success); }
|
||||||
|
|
||||||
.more-btn {
|
.more-btn {
|
||||||
width: auto; height: auto;
|
width: auto; height: auto;
|
||||||
display: inline-flex; align-items: center; justify-content: center;
|
display: inline-flex; align-items: center; justify-content: center;
|
||||||
border: 0; background: transparent;
|
border: 0; background: transparent;
|
||||||
color: #2563eb; font-size: 13px; font-weight: 800;
|
color: var(--theme-primary-active); font-size: 13px; font-weight: 800;
|
||||||
}
|
}
|
||||||
.more-btn:hover { color: #059669; }
|
.more-btn:hover { color: var(--theme-primary-active); }
|
||||||
|
|
||||||
.list-foot {
|
.list-foot {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -272,8 +272,8 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
font-size: 14px; font-weight: 800;
|
font-size: 14px; font-weight: 800;
|
||||||
transition: background 160ms ease, color 160ms ease, box-shadow 160ms ease;
|
transition: background 160ms ease, color 160ms ease, box-shadow 160ms ease;
|
||||||
}
|
}
|
||||||
.pager button:hover:not(.active) { background: #fff; color: #059669; box-shadow: 0 1px 4px rgba(15, 23, 42, .08); }
|
.pager button:hover:not(.active) { background: #fff; color: var(--theme-primary-active); box-shadow: 0 1px 4px rgba(15, 23, 42, .08); }
|
||||||
.pager button.active { background: #059669; color: #fff; box-shadow: 0 8px 16px rgba(5, 150, 105, .20); }
|
.pager button.active { background: var(--theme-primary); color: #fff; box-shadow: 0 8px 16px var(--theme-primary-shadow); }
|
||||||
.pager span { color: #64748b; font-weight: 800; }
|
.pager span { color: #64748b; font-weight: 800; }
|
||||||
|
|
||||||
.page-size {
|
.page-size {
|
||||||
@@ -318,8 +318,8 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: linear-gradient(135deg, #dbeafe, #ecfdf5);
|
background: linear-gradient(135deg, var(--theme-primary-soft-strong), var(--theme-primary-soft));
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
@@ -334,8 +334,8 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
padding: 3px 9px;
|
padding: 3px 9px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: #dcfce7;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,16 +377,16 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-pill.high { background: #fee2e2; color: #ef4444; }
|
.risk-pill.high { background: var(--danger-soft); color: var(--danger); }
|
||||||
.risk-pill.medium { background: #ffedd5; color: #f97316; }
|
.risk-pill.medium { background: var(--warning-soft); color: var(--warning-active); }
|
||||||
.risk-pill.low { background: #dcfce7; color: #059669; }
|
.risk-pill.low { background: var(--success-soft); color: var(--success); }
|
||||||
.state-pill { background: #dbeafe; color: #2563eb; }
|
.state-pill { background: var(--theme-primary-soft); color: var(--theme-primary-active); }
|
||||||
|
|
||||||
.countdown {
|
.countdown {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
color: #f97316 !important;
|
color: var(--warning-active) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-summary-panel {
|
.hero-summary-panel {
|
||||||
@@ -417,7 +417,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hero-summary-icon {
|
.hero-summary-icon {
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,8 +456,8 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 4px rgba(16, 185, 129, .12);
|
box-shadow: 0 0 0 4px rgba(var(--theme-primary-rgb), .12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-line {
|
.progress-line {
|
||||||
@@ -485,7 +485,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
background: #dbe4ee;
|
background: #dbe4ee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.active::before { background: #10b981; }
|
.progress-step.active::before { background: var(--theme-primary); }
|
||||||
.progress-step:first-child::before { left: 50%; }
|
.progress-step:first-child::before { left: 50%; }
|
||||||
.progress-step:last-child::before { right: 50%; }
|
.progress-step:last-child::before { right: 50%; }
|
||||||
|
|
||||||
@@ -507,20 +507,20 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
inset: -4px;
|
inset: -4px;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
border: 2px solid rgba(16, 185, 129, .42);
|
border: 2px solid rgba(var(--theme-primary-rgb), .42);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.active span {
|
.progress-step.active span {
|
||||||
background: #059669;
|
background: var(--theme-primary-active);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.current span {
|
.progress-step.current span {
|
||||||
background: #10b981 !important;
|
background: var(--theme-primary) !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
box-shadow: 0 0 0 4px rgba(16, 185, 129, .15) !important;
|
box-shadow: 0 0 0 4px rgba(var(--theme-primary-rgb), .15) !important;
|
||||||
animation: breathe-dot 3s ease-in-out infinite !important;
|
animation: breathe-dot 3s ease-in-out infinite !important;
|
||||||
transform-origin: center !important;
|
transform-origin: center !important;
|
||||||
}
|
}
|
||||||
@@ -528,11 +528,11 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
@keyframes breathe-dot {
|
@keyframes breathe-dot {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
box-shadow: 0 4px 12px rgba(16, 185, 129, .3), 0 0 0 4px rgba(16, 185, 129, .15);
|
box-shadow: 0 4px 12px rgba(var(--theme-primary-rgb), .3), 0 0 0 4px rgba(var(--theme-primary-rgb), .15);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
transform: scale(1.12);
|
transform: scale(1.12);
|
||||||
box-shadow: 0 4px 20px rgba(16, 185, 129, .5), 0 0 0 10px rgba(16, 185, 129, .08);
|
box-shadow: 0 4px 20px rgba(var(--theme-primary-rgb), .5), 0 0 0 10px rgba(var(--theme-primary-rgb), .08);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,11 +541,11 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.current strong { color: #059669; }
|
.progress-step.current strong { color: var(--theme-primary-active); }
|
||||||
.progress-step small { font-size: 11px; }
|
.progress-step small { font-size: 11px; }
|
||||||
|
|
||||||
.progress-step.current small {
|
.progress-step.current small {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-grid {
|
.detail-grid {
|
||||||
@@ -596,9 +596,9 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
min-width: 102px;
|
min-width: 102px;
|
||||||
min-height: 34px;
|
min-height: 34px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border-radius: 999px;
|
border-radius: 4px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
@@ -689,19 +689,19 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
width: max-content;
|
width: max-content;
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
border-radius: 999px;
|
border-radius: 4px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.over-tag.ok {
|
.over-tag.ok {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.over-tag.bad {
|
.over-tag.bad {
|
||||||
background: #fef2f2;
|
background: var(--danger-soft);
|
||||||
color: #ef4444;
|
color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.expense-attachment-main {
|
.expense-attachment-main {
|
||||||
@@ -717,22 +717,22 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 24px;
|
min-height: 24px;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
border-radius: 999px;
|
border-radius: 4px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment-pill.ok { background: #ecfdf5; color: #059669; }
|
.attachment-pill.ok { background: var(--success-soft); color: var(--success); }
|
||||||
.attachment-pill.partial { background: #fff7ed; color: #ea580c; }
|
.attachment-pill.partial { background: var(--warning-soft); color: var(--warning-active); }
|
||||||
.attachment-pill.missing { background: #fef2f2; color: #ef4444; }
|
.attachment-pill.missing { background: var(--danger-soft); color: var(--danger); }
|
||||||
.attachment-pill.neutral { background: #eef2ff; color: #4f46e5; }
|
.attachment-pill.neutral { background: var(--info-soft); color: var(--info); }
|
||||||
|
|
||||||
.inline-action {
|
.inline-action {
|
||||||
min-height: 24px;
|
min-height: 24px;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
border: 1px solid #dbe4ee;
|
border: 1px solid #dbe4ee;
|
||||||
border-radius: 999px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
@@ -740,13 +740,13 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.inline-action:hover {
|
.inline-action:hover {
|
||||||
border-color: rgba(16, 185, 129, .36);
|
border-color: rgba(var(--theme-primary-rgb), .36);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-inline-tag.low { background: #ecfdf5; color: #059669; }
|
.risk-inline-tag.low { background: var(--success-soft); color: var(--success); }
|
||||||
.risk-inline-tag.medium { background: #fff7ed; color: #ea580c; }
|
.risk-inline-tag.medium { background: var(--warning-soft); color: var(--warning-active); }
|
||||||
.risk-inline-tag.high { background: #fef2f2; color: #dc2626; }
|
.risk-inline-tag.high { background: var(--danger-soft); color: var(--danger-hover); }
|
||||||
|
|
||||||
.expense-risk p {
|
.expense-risk p {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
@@ -773,7 +773,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
border-radius: 999px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #e2e8f0;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
@@ -782,7 +782,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.expense-file-chip i {
|
.expense-file-chip i {
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,13 +814,13 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detail-attachment.missing {
|
.detail-attachment.missing {
|
||||||
border-color: #fb923c;
|
border-color: var(--warning-line);
|
||||||
border-style: dashed;
|
border-style: dashed;
|
||||||
background: #fff7ed;
|
background: var(--warning-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-attachment i { color: #059669; font-size: 24px; }
|
.detail-attachment i { color: var(--theme-primary); font-size: 24px; }
|
||||||
.detail-attachment.missing i { color: #f97316; }
|
.detail-attachment.missing i { color: var(--warning-active); }
|
||||||
|
|
||||||
.detail-attachment strong {
|
.detail-attachment strong {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -862,7 +862,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
font-weight: 750;
|
font-weight: 750;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-card header b { color: #ef4444; }
|
.risk-card header b { color: var(--danger); }
|
||||||
|
|
||||||
.risk-list {
|
.risk-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -883,9 +883,9 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.risk-list div:last-child { border-bottom: 0; }
|
.risk-list div:last-child { border-bottom: 0; }
|
||||||
.risk-list i { color: #f97316; }
|
.risk-list i { color: var(--warning-active); }
|
||||||
.risk-list b.high { color: #ef4444; }
|
.risk-list b.high { color: var(--danger); }
|
||||||
.risk-list b.medium { color: #f97316; }
|
.risk-list b.medium { color: var(--warning-active); }
|
||||||
|
|
||||||
.risk-note {
|
.risk-note {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
@@ -951,24 +951,24 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
|
|
||||||
.approve-action {
|
.approve-action {
|
||||||
min-width: 92px;
|
min-width: 92px;
|
||||||
border: 1px solid #059669;
|
border: 1px solid var(--theme-primary);
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 4px 10px rgba(5, 150, 105, .14);
|
box-shadow: 0 4px 10px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.reject-action {
|
.reject-action {
|
||||||
min-width: 86px;
|
min-width: 86px;
|
||||||
border: 1px solid #fecaca;
|
border: 1px solid var(--danger-line);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #ef4444;
|
color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.supplement-action {
|
.supplement-action {
|
||||||
min-width: 86px;
|
min-width: 86px;
|
||||||
border: 1px solid #fed7aa;
|
border: 1px solid var(--warning-line);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #ea580c;
|
color: var(--warning-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ────────── Detail Modal Overlay ────────── */
|
/* ────────── Detail Modal Overlay ────────── */
|
||||||
@@ -1020,9 +1020,9 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
.req-badge {
|
.req-badge {
|
||||||
padding: 6px 14px;
|
padding: 6px 14px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: #eff6ff;
|
background: var(--theme-primary-soft);
|
||||||
border-left: 3px solid #1d4ed8;
|
border-left: 3px solid var(--theme-primary-active);
|
||||||
color: #1d4ed8;
|
color: var(--theme-primary-active);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
letter-spacing: .02em;
|
letter-spacing: .02em;
|
||||||
@@ -1058,23 +1058,23 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header-indicator.high {
|
.header-indicator.high {
|
||||||
background: #fee2e2;
|
background: var(--danger-soft);
|
||||||
color: #dc2626;
|
color: var(--danger-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-indicator.medium {
|
.header-indicator.medium {
|
||||||
background: #ffedd5;
|
background: var(--warning-soft);
|
||||||
color: #ea580c;
|
color: var(--warning-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-indicator.low {
|
.header-indicator.low {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-indicator.status {
|
.header-indicator.status {
|
||||||
background: #dbeafe;
|
background: var(--theme-primary-soft);
|
||||||
color: #1d4ed8;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-btn {
|
.close-btn {
|
||||||
@@ -1128,14 +1128,14 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
|
|
||||||
.progress-node.done .node-dot,
|
.progress-node.done .node-dot,
|
||||||
.progress-node.active .node-dot {
|
.progress-node.active .node-dot {
|
||||||
background: #059669;
|
background: var(--theme-primary-active);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 4px 12px rgba(5, 150, 105, .25);
|
box-shadow: 0 4px 12px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-node.current .node-dot {
|
.progress-node.current .node-dot {
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
box-shadow: 0 4px 12px rgba(5, 150, 105, .25), 0 0 0 5px rgba(5, 150, 105, .1);
|
box-shadow: 0 4px 12px var(--theme-primary-shadow), 0 0 0 5px rgba(var(--theme-primary-rgb), .1);
|
||||||
animation: breathe-pulse 2s ease-in-out infinite;
|
animation: breathe-pulse 2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1143,12 +1143,12 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
0%, 100% {
|
0%, 100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
box-shadow: 0 4px 12px rgba(5, 150, 105, .25), 0 0 0 4px rgba(5, 150, 105, .15);
|
box-shadow: 0 4px 12px var(--theme-primary-shadow), 0 0 0 4px rgba(var(--theme-primary-rgb), .15);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
box-shadow: 0 4px 12px rgba(5, 150, 105, .4), 0 0 0 10px rgba(5, 150, 105, .08);
|
box-shadow: 0 4px 12px rgba(var(--theme-primary-rgb), .4), 0 0 0 10px rgba(var(--theme-primary-rgb), .08);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,7 +1166,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-node.current .node-label strong { color: #059669; }
|
.progress-node.current .node-label strong { color: var(--theme-primary-active); }
|
||||||
|
|
||||||
.node-label small {
|
.node-label small {
|
||||||
color: #94a3b8;
|
color: #94a3b8;
|
||||||
@@ -1185,7 +1185,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
transition: background 300ms ease;
|
transition: background 300ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.node-line.filled { background: #10b981; }
|
.node-line.filled { background: var(--theme-primary); }
|
||||||
|
|
||||||
/* ── Modal Body ── */
|
/* ── Modal Body ── */
|
||||||
.modal-body {
|
.modal-body {
|
||||||
@@ -1220,10 +1220,10 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
transition: background 160ms ease;
|
transition: background 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-block:hover { background: #fafffe; }
|
.metric-block:hover { background: #f8fbff; }
|
||||||
|
|
||||||
.metric-block.amount {
|
.metric-block.amount {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-label {
|
.metric-label {
|
||||||
@@ -1245,9 +1245,9 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.metric-value.sla { display: flex; align-items: center; gap: 6px; font-size: 20px; }
|
.metric-value.sla { display: flex; align-items: center; gap: 6px; font-size: 20px; }
|
||||||
.metric-value.sla.safe { color: #059669; }
|
.metric-value.sla.safe { color: var(--success); }
|
||||||
.metric-value.sla.warning { color: #f59e0b; }
|
.metric-value.sla.warning { color: var(--warning); }
|
||||||
.metric-value.sla.danger { color: #ef4444; }
|
.metric-value.sla.danger { color: var(--danger); }
|
||||||
|
|
||||||
/* ── Content Card ── */
|
/* ── Content Card ── */
|
||||||
.content-card {
|
.content-card {
|
||||||
@@ -1284,7 +1284,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card-title i {
|
.card-title i {
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1297,15 +1297,15 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
.card-badge {
|
.card-badge {
|
||||||
padding: 4px 10px;
|
padding: 4px 10px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: #f0fdf4;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-badge.warn {
|
.card-badge.warn {
|
||||||
background: #fff7ed;
|
background: var(--warning-soft);
|
||||||
color: #ea580c;
|
color: var(--warning-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Summary Grid ── */
|
/* ── Summary Grid ── */
|
||||||
@@ -1325,14 +1325,14 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
transition: background 160ms ease;
|
transition: background 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-cell:hover { background: #fafffe; }
|
.summary-cell:hover { background: #f8fbff; }
|
||||||
|
|
||||||
.cell-icon {
|
.cell-icon {
|
||||||
width: 38px; height: 38px;
|
width: 38px; height: 38px;
|
||||||
display: grid; place-items: center;
|
display: grid; place-items: center;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
@@ -1402,7 +1402,7 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
.total-amount {
|
.total-amount {
|
||||||
color: #059669 !important;
|
color: var(--theme-primary-active) !important;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1416,8 +1416,8 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.over-badge.ok { background: #ecfdf5; color: #059669; }
|
.over-badge.ok { background: var(--success-soft); color: var(--success); }
|
||||||
.over-badge.bad { background: #fef2f2; color: #ef4444; }
|
.over-badge.bad { background: var(--danger-soft); color: var(--danger); }
|
||||||
|
|
||||||
/* ── Attachments (sidebar list) ── */
|
/* ── Attachments (sidebar list) ── */
|
||||||
.attachment-list-side {
|
.attachment-list-side {
|
||||||
@@ -1440,8 +1440,8 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
.attachment-row:hover { background: #fafbfd; }
|
.attachment-row:hover { background: #fafbfd; }
|
||||||
|
|
||||||
.attachment-row.missing {
|
.attachment-row.missing {
|
||||||
border: 1px dashed #fbbf24;
|
border: 1px dashed var(--warning-line);
|
||||||
background: #fffbeb;
|
background: var(--warning-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-icon-sm {
|
.file-icon-sm {
|
||||||
@@ -1452,9 +1452,9 @@ tbody tr:last-child td { border-bottom: 0; }
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-icon-sm.pdf { background: #fef2f2; color: #ef4444; }
|
.file-icon-sm.pdf { background: var(--danger-soft); color: var(--danger); }
|
||||||
.file-icon-sm.img { background: #ecfdf5; color: #059669; }
|
.file-icon-sm.img { background: var(--theme-primary-soft); color: var(--theme-primary); }
|
||||||
.file-icon-sm.miss { background: #fff7ed; color: #f59e0b; }
|
.file-icon-sm.miss { background: var(--warning-soft); color: var(--warning); }
|
||||||
|
|
||||||
.file-detail strong {
|
.file-detail strong {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.archive-page .status-tag.archived {
|
.archive-page .status-tag.archived {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
background: rgba(16, 185, 129, 0.12);
|
background: var(--theme-primary-soft);
|
||||||
border: 1px solid rgba(16, 185, 129, 0.22);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.archive-page .risk-tag.none {
|
.archive-page .risk-tag.none {
|
||||||
@@ -9,44 +9,45 @@
|
|||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.archive-dropdown-filter {
|
.archive-filter-control {
|
||||||
position: relative;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.archive-dropdown-menu {
|
.archive-filter-trigger {
|
||||||
position: absolute;
|
gap: 10px;
|
||||||
top: calc(100% + 8px);
|
}
|
||||||
left: 0;
|
|
||||||
z-index: 12;
|
.archive-filter-trigger:focus-visible {
|
||||||
min-width: 148px;
|
border-color: var(--theme-primary);
|
||||||
max-height: 280px;
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.archive-filter-menu) {
|
||||||
|
min-width: 156px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.archive-filter-menu .el-dropdown-menu) {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 16px 32px rgba(15, 23, 42, 0.12);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.archive-dropdown-option {
|
:global(.archive-filter-option) {
|
||||||
display: block;
|
min-height: 34px;
|
||||||
width: 100%;
|
border-radius: 4px;
|
||||||
min-height: 36px;
|
|
||||||
padding: 0 12px;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: transparent;
|
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-align: left;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.archive-dropdown-option:hover,
|
:global(.archive-filter-option .mdi-check) {
|
||||||
.archive-dropdown-option.active {
|
margin-right: 8px;
|
||||||
background: rgba(16, 185, 129, 0.1);
|
color: var(--theme-primary-active);
|
||||||
color: #047857;
|
}
|
||||||
|
|
||||||
|
:global(.archive-filter-option.is-active),
|
||||||
|
:global(.archive-filter-option:hover) {
|
||||||
|
background: var(--theme-primary-soft);
|
||||||
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.archive-page .hint {
|
.archive-page .hint {
|
||||||
|
|||||||
@@ -56,8 +56,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.compare-sheet-list b.success {
|
.compare-sheet-list b.success {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.compare-sheet-list b.danger {
|
.compare-sheet-list b.danger {
|
||||||
@@ -106,8 +106,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.compare-table-wrap td b.success {
|
.compare-table-wrap td b.success {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.compare-table-wrap td b.warning {
|
.compare-table-wrap td b.warning {
|
||||||
@@ -151,8 +151,8 @@
|
|||||||
.review-submit-form input:focus,
|
.review-submit-form input:focus,
|
||||||
.review-submit-form select:focus {
|
.review-submit-form select:focus {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
border-color: rgba(16, 185, 129, 0.5);
|
border-color: rgba(var(--theme-primary-rgb), 0.5);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-submit-test-state,
|
.review-submit-test-state,
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-submit-test-state strong.passed {
|
.review-submit-test-state strong.passed {
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-submit-test-state p {
|
.review-submit-test-state p {
|
||||||
@@ -335,7 +335,7 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-top: 14px;
|
margin-top: 14px;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
border: 1px solid rgba(14, 165, 233, 0.22);
|
border: 1px solid rgba(58, 124, 165, 0.22);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: linear-gradient(180deg, rgba(240, 249, 255, 0.96), rgba(224, 242, 254, 0.9));
|
background: linear-gradient(180deg, rgba(240, 249, 255, 0.96), rgba(224, 242, 254, 0.9));
|
||||||
color: #075985;
|
color: #075985;
|
||||||
@@ -417,10 +417,10 @@
|
|||||||
min-height: 38px;
|
min-height: 38px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border: 1px solid #e0f2fe;
|
border: 1px solid #eaf4fa;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: #f0f9ff;
|
background: #f0f9ff;
|
||||||
color: #0369a1;
|
color: #255b7d;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@@ -451,8 +451,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.reviewer-card {
|
.reviewer-card {
|
||||||
border-color: rgba(16, 185, 129, 0.24);
|
border-color: rgba(var(--theme-primary-rgb), 0.24);
|
||||||
background: linear-gradient(180deg, #ffffff, #f8fffc);
|
background: linear-gradient(180deg, #ffffff, var(--theme-primary-soft));
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-list {
|
.review-list {
|
||||||
@@ -515,7 +515,7 @@
|
|||||||
|
|
||||||
.version-row.active {
|
.version-row.active {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: rgba(16, 185, 129, 0.08);
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-main {
|
.version-main {
|
||||||
@@ -564,8 +564,8 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 7px;
|
padding: 0 7px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
@@ -599,8 +599,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.version-state.success {
|
.version-state.success {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-state.warning {
|
.version-state.warning {
|
||||||
@@ -814,8 +814,8 @@
|
|||||||
|
|
||||||
.test-state.success,
|
.test-state.success,
|
||||||
.tool-state.safe {
|
.tool-state.safe {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-state.warning,
|
.test-state.warning,
|
||||||
@@ -908,7 +908,7 @@
|
|||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
accent-color: #0f766e;
|
accent-color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-rule-create-toggle span {
|
.risk-rule-create-toggle span {
|
||||||
@@ -963,8 +963,8 @@
|
|||||||
.risk-rule-create-form select:focus,
|
.risk-rule-create-form select:focus,
|
||||||
.risk-rule-create-form textarea:focus {
|
.risk-rule-create-form textarea:focus {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
border-color: rgba(16, 185, 129, 0.5);
|
border-color: rgba(var(--theme-primary-rgb), 0.5);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-rule-create-form input:not([type='checkbox'])::placeholder,
|
.risk-rule-create-form input:not([type='checkbox'])::placeholder,
|
||||||
@@ -984,7 +984,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.publish-summary strong {
|
.publish-summary strong {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
@@ -1031,8 +1031,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.minor-action.success-action {
|
.minor-action.success-action {
|
||||||
border-color: rgba(5, 150, 105, 0.26);
|
border-color: rgba(var(--success-rgb), 0.26);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.minor-action.enable-action {
|
.minor-action.enable-action {
|
||||||
@@ -1041,8 +1041,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.minor-action.enable-action.is-on {
|
.minor-action.enable-action.is-on {
|
||||||
border-color: rgba(5, 150, 105, 0.26);
|
border-color: rgba(var(--success-rgb), 0.26);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.minor-action.enable-action i {
|
.minor-action.enable-action i {
|
||||||
@@ -1167,10 +1167,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.major-action {
|
.major-action {
|
||||||
border: 1px solid #059669;
|
border: 1px solid var(--theme-primary);
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 4px 12px rgba(5, 150, 105, .16);
|
box-shadow: 0 4px 12px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-action:hover,
|
.back-action:hover,
|
||||||
@@ -1216,8 +1216,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mini-btn.primary {
|
.mini-btn.primary {
|
||||||
border-color: #059669;
|
border-color: var(--theme-primary);
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1584,8 +1584,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.json-risk-mode-pill.low {
|
.json-risk-mode-pill.low {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.json-risk-editor-body {
|
.json-risk-editor-body {
|
||||||
@@ -1760,8 +1760,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.json-risk-meta-badge.test-passed {
|
.json-risk-meta-badge.test-passed {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.json-risk-meta-badge.test-pending {
|
.json-risk-meta-badge.test-pending {
|
||||||
@@ -1785,8 +1785,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.meta-status-indicator.is-active .indicator-dot {
|
.meta-status-indicator.is-active .indicator-dot {
|
||||||
background: #10b981;
|
background: var(--success);
|
||||||
box-shadow: 0 0 4px rgba(16, 185, 129, 0.4);
|
box-shadow: 0 0 4px rgba(var(--success-rgb), 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.json-risk-editor-toolbar {
|
.json-risk-editor-toolbar {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
bottom: -13px;
|
bottom: -13px;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-toolbar {
|
.list-toolbar {
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 0 11px;
|
padding: 0 11px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
@@ -118,8 +118,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.search-filter:focus-within {
|
.search-filter:focus-within {
|
||||||
border-color: rgba(16, 185, 129, 0.48);
|
border-color: rgba(var(--theme-primary-rgb), 0.48);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-trigger,
|
.picker-trigger,
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
.create-btn,
|
.create-btn,
|
||||||
.row-action {
|
.row-action {
|
||||||
min-height: 38px;
|
min-height: 38px;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 760;
|
font-weight: 760;
|
||||||
}
|
}
|
||||||
@@ -166,9 +166,9 @@
|
|||||||
|
|
||||||
.picker-trigger:hover,
|
.picker-trigger:hover,
|
||||||
.picker-filter.open .picker-trigger {
|
.picker-filter.open .picker-trigger {
|
||||||
border-color: rgba(16, 185, 129, 0.34);
|
border-color: rgba(var(--theme-primary-rgb), 0.34);
|
||||||
background: #f6fffb;
|
background: var(--theme-primary-soft);
|
||||||
color: #0f9f78;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-popover {
|
.picker-popover {
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 18px 42px rgba(15, 23, 42, 0.16);
|
box-shadow: 0 18px 42px rgba(15, 23, 42, 0.16);
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -237,9 +237,9 @@
|
|||||||
|
|
||||||
.picker-option:hover,
|
.picker-option:hover,
|
||||||
.picker-option.active {
|
.picker-option.active {
|
||||||
border-color: rgba(16, 185, 129, 0.32);
|
border-color: rgba(var(--theme-primary-rgb), 0.32);
|
||||||
background: rgba(16, 185, 129, 0.08);
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-actions {
|
.toolbar-actions {
|
||||||
@@ -259,8 +259,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ghost-filter-btn:hover {
|
.ghost-filter-btn:hover {
|
||||||
border-color: rgba(16, 185, 129, 0.28);
|
border-color: rgba(var(--theme-primary-rgb), 0.28);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-btn {
|
.create-btn {
|
||||||
@@ -269,9 +269,9 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 18px rgba(5, 150, 105, 0.18);
|
box-shadow: 0 8px 18px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-btn:disabled {
|
.create-btn:disabled {
|
||||||
@@ -307,8 +307,8 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(16, 185, 129, 0.1);
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -376,7 +376,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.table-state.empty i {
|
.table-state.empty i {
|
||||||
color: #0ea5e9;
|
color: #3a7ca5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-state p,
|
.table-state p,
|
||||||
@@ -402,10 +402,10 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.28);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.28);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 760;
|
font-weight: 760;
|
||||||
}
|
}
|
||||||
@@ -487,7 +487,7 @@ tbody tr.is-disabled:hover {
|
|||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill-avatar.emerald { background: linear-gradient(135deg, #10b981, #059669); }
|
.skill-avatar.primary { background: var(--theme-gradient-primary); }
|
||||||
.skill-avatar.rose { background: linear-gradient(135deg, #f43f5e, #e11d48); }
|
.skill-avatar.rose { background: linear-gradient(135deg, #f43f5e, #e11d48); }
|
||||||
.skill-avatar.violet { background: linear-gradient(135deg, #8b5cf6, #7c3aed); }
|
.skill-avatar.violet { background: linear-gradient(135deg, #8b5cf6, #7c3aed); }
|
||||||
.skill-avatar.blue { background: linear-gradient(135deg, #3b82f6, #2563eb); }
|
.skill-avatar.blue { background: linear-gradient(135deg, #3b82f6, #2563eb); }
|
||||||
@@ -529,8 +529,8 @@ tbody tr.is-disabled:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.success {
|
.status-pill.success {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.warning {
|
.status-pill.warning {
|
||||||
@@ -544,8 +544,8 @@ tbody tr.is-disabled:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.info {
|
.status-pill.info {
|
||||||
background: #e0f2fe;
|
background: #eaf4fa;
|
||||||
color: #0284c7;
|
color: #2f6d95;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.danger {
|
.status-pill.danger {
|
||||||
@@ -560,13 +560,13 @@ tbody tr.is-disabled:hover {
|
|||||||
|
|
||||||
.row-action {
|
.row-action {
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.32);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.32);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.row-action:hover {
|
.row-action:hover {
|
||||||
background: rgba(16, 185, 129, 0.08);
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-scroll {
|
.detail-scroll {
|
||||||
@@ -620,7 +620,7 @@ tbody tr.is-disabled:hover {
|
|||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill-badge.emerald { background: linear-gradient(135deg, #10b981, #059669); }
|
.skill-badge.primary { background: var(--theme-gradient-primary); }
|
||||||
.skill-badge.rose { background: linear-gradient(135deg, #f43f5e, #e11d48); }
|
.skill-badge.rose { background: linear-gradient(135deg, #f43f5e, #e11d48); }
|
||||||
.skill-badge.violet { background: linear-gradient(135deg, #8b5cf6, #7c3aed); }
|
.skill-badge.violet { background: linear-gradient(135deg, #8b5cf6, #7c3aed); }
|
||||||
.skill-badge.blue { background: linear-gradient(135deg, #3b82f6, #2563eb); }
|
.skill-badge.blue { background: linear-gradient(135deg, #3b82f6, #2563eb); }
|
||||||
@@ -658,9 +658,9 @@ tbody tr.is-disabled:hover {
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.16);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.16);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: linear-gradient(180deg, #f8fffc, #ffffff);
|
background: linear-gradient(180deg, var(--theme-primary-soft), #ffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-note-block strong {
|
.review-note-block strong {
|
||||||
@@ -695,7 +695,7 @@ tbody tr.is-disabled:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hero-review-meta i {
|
.hero-review-meta i {
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1041,12 +1041,12 @@ tbody tr.is-disabled:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.version-pair-card.published {
|
.version-pair-card.published {
|
||||||
background: rgba(16, 185, 129, 0.1);
|
background: var(--success-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-pair-card.published b {
|
.version-pair-card.published b {
|
||||||
background: #dcfce7;
|
background: var(--success-line);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-pair-card.working {
|
.version-pair-card.working {
|
||||||
@@ -1115,8 +1115,8 @@ tbody tr.is-disabled:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.change-center-item.active {
|
.change-center-item.active {
|
||||||
border-color: rgba(16, 185, 129, 0.35);
|
border-color: rgba(var(--theme-primary-rgb), 0.35);
|
||||||
background: rgba(16, 185, 129, 0.05);
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.change-center-item > button {
|
.change-center-item > button {
|
||||||
@@ -1176,13 +1176,13 @@ tbody tr.is-disabled:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.change-record-item:hover {
|
.change-record-item:hover {
|
||||||
border-color: rgba(16, 185, 129, 0.35);
|
border-color: rgba(var(--theme-primary-rgb), 0.35);
|
||||||
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.08);
|
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.08);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.change-record-item:focus-visible {
|
.change-record-item:focus-visible {
|
||||||
outline: 3px solid rgba(16, 185, 129, 0.18);
|
outline: 3px solid var(--theme-focus-ring);
|
||||||
outline-offset: 1px;
|
outline-offset: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1387,8 +1387,8 @@ tbody tr.is-disabled:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.rule-timeline-item > i.success {
|
.rule-timeline-item > i.success {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rule-timeline-item > i.warning {
|
.rule-timeline-item > i.warning {
|
||||||
@@ -1459,15 +1459,6 @@ tbody tr.is-disabled:hover {
|
|||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
|
|
||||||
.compare-toolbar select {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 40px;
|
|
||||||
padding: 0 12px;
|
|
||||||
border: 1px solid #cbd5e1;
|
|
||||||
border-radius: 12px;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.compare-toolbar i {
|
.compare-toolbar i {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: #94a3b8;
|
color: #94a3b8;
|
||||||
@@ -1512,4 +1503,3 @@ tbody tr.is-disabled:hover {
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top, rgba(16, 185, 129, 0.16), transparent 32%),
|
radial-gradient(circle at top, rgba(var(--theme-primary-rgb), 0.16), transparent 32%),
|
||||||
linear-gradient(180deg, #08130f 0%, #0f1f18 100%);
|
linear-gradient(180deg, #08130f 0%, #0f1f18 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
background: linear-gradient(135deg, rgba(16, 185, 129, 0.2), rgba(5, 150, 105, 0.28));
|
background: linear-gradient(135deg, rgba(var(--theme-primary-rgb), 0.2), rgba(var(--theme-primary-rgb), 0.28));
|
||||||
color: #4ade80;
|
color: var(--theme-primary-soft-strong);
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,13 +56,13 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.2);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.2);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 760;
|
font-weight: 760;
|
||||||
box-shadow: 0 16px 30px rgba(5, 150, 105, 0.2);
|
box-shadow: 0 16px 30px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.retry-btn:disabled {
|
.retry-btn:disabled {
|
||||||
|
|||||||
@@ -111,13 +111,11 @@
|
|||||||
.budget-edit-form-grid label.required > span::after {
|
.budget-edit-form-grid label.required > span::after {
|
||||||
content: "*";
|
content: "*";
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
color: #ef4444;
|
color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-form-grid select,
|
|
||||||
.budget-edit-textarea textarea,
|
.budget-edit-textarea textarea,
|
||||||
.budget-edit-table input,
|
.budget-edit-table input {
|
||||||
.budget-edit-table select {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid #dbe4ee;
|
border: 1px solid #dbe4ee;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -128,17 +126,15 @@
|
|||||||
transition: border-color 160ms ease, box-shadow 160ms ease;
|
transition: border-color 160ms ease, box-shadow 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-form-grid select {
|
.budget-edit-form-grid .enterprise-select,
|
||||||
height: 38px;
|
.budget-edit-table .enterprise-select {
|
||||||
padding: 0 34px 0 12px;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-form-grid select:focus,
|
|
||||||
.budget-edit-textarea textarea:focus,
|
.budget-edit-textarea textarea:focus,
|
||||||
.budget-edit-table input:focus,
|
.budget-edit-table input:focus {
|
||||||
.budget-edit-table select:focus {
|
border-color: var(--theme-primary);
|
||||||
border-color: #10b981;
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, .12);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-textarea {
|
.budget-edit-textarea {
|
||||||
@@ -207,7 +203,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-table th i {
|
.budget-edit-table th i {
|
||||||
color: #ef4444;
|
color: var(--danger);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,8 +213,7 @@
|
|||||||
.budget-edit-table th:nth-child(4) { width: 120px; }
|
.budget-edit-table th:nth-child(4) { width: 120px; }
|
||||||
.budget-edit-table th:nth-child(6) { width: 68px; }
|
.budget-edit-table th:nth-child(6) { width: 68px; }
|
||||||
|
|
||||||
.budget-edit-table input,
|
.budget-edit-table input {
|
||||||
.budget-edit-table select {
|
|
||||||
height: 34px;
|
height: 34px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -242,8 +237,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-row-delete:hover {
|
.budget-row-delete:hover {
|
||||||
background: #fef2f2;
|
background: var(--danger-soft);
|
||||||
color: #dc2626;
|
color: var(--danger-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-add-row-btn {
|
.budget-add-row-btn {
|
||||||
@@ -253,10 +248,10 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
border: 1px solid rgba(16, 185, 129, .42);
|
border: 1px solid rgba(var(--theme-primary-rgb), .42);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -284,7 +279,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-total strong {
|
.budget-edit-total strong {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -315,16 +310,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-draft {
|
.budget-edit-draft {
|
||||||
border: 1px solid #10b981;
|
border: 1px solid var(--theme-primary);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-publish {
|
.budget-edit-publish {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 10px 24px rgba(5, 150, 105, .20);
|
box-shadow: 0 10px 24px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-dialog-fade-enter-active,
|
.budget-dialog-fade-enter-active,
|
||||||
@@ -421,10 +416,6 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-form-grid select {
|
|
||||||
height: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.budget-edit-textarea {
|
.budget-edit-textarea {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
@@ -441,8 +432,7 @@
|
|||||||
padding: 6px 8px;
|
padding: 6px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-edit-table input,
|
.budget-edit-table input {
|
||||||
.budget-edit-table select {
|
|
||||||
height: 30px;
|
height: 30px;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-summary-card {
|
.budget-summary-card {
|
||||||
--accent: #10b981;
|
--accent: var(--theme-primary);
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 112px;
|
min-height: 112px;
|
||||||
padding: 12px 14px 10px;
|
padding: 12px 14px 10px;
|
||||||
@@ -35,16 +35,16 @@
|
|||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-summary-card.green {
|
.budget-summary-card.primary {
|
||||||
--accent: #10b981;
|
--accent: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-summary-card.blue {
|
.budget-summary-card.info {
|
||||||
--accent: #3b82f6;
|
--accent: var(--theme-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-summary-card.orange {
|
.budget-summary-card.warning {
|
||||||
--accent: #f59e0b;
|
--accent: var(--warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-summary-head {
|
.budget-summary-head {
|
||||||
@@ -134,13 +134,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.comparison-pill.up {
|
.comparison-pill.up {
|
||||||
background: rgba(22, 163, 74, .08);
|
background: var(--success-soft);
|
||||||
color: #16a34a;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.comparison-pill.down {
|
.comparison-pill.down {
|
||||||
background: rgba(239, 68, 68, .08);
|
background: var(--danger-soft);
|
||||||
color: #dc2626;
|
color: var(--danger-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-filter-bar {
|
.budget-filter-bar {
|
||||||
@@ -173,35 +173,15 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-filter-bar select {
|
.budget-filter-bar .enterprise-select {
|
||||||
min-height: 38px;
|
|
||||||
min-width: 128px;
|
min-width: 128px;
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: #fff;
|
|
||||||
color: #334155;
|
|
||||||
padding: 0 34px 0 14px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 750;
|
|
||||||
transition: border-color 160ms ease, box-shadow 160ms ease, color 160ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.budget-filter-bar select:hover {
|
|
||||||
border-color: rgba(16, 185, 129, .32);
|
|
||||||
color: #0f9f78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.budget-filter-bar select:focus {
|
|
||||||
border-color: #10b981;
|
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, .14);
|
|
||||||
outline: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-primary-btn {
|
.budget-primary-btn {
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 10px;
|
border-radius: 8px;
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -212,13 +192,13 @@
|
|||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 0 10px 24px rgba(5, 150, 105, .2);
|
box-shadow: 0 10px 24px var(--theme-primary-shadow);
|
||||||
transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
|
transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-primary-btn:hover {
|
.budget-primary-btn:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 0 14px 28px rgba(5, 150, 105, .24);
|
box-shadow: 0 14px 28px rgba(var(--theme-primary-rgb), .24);
|
||||||
filter: saturate(1.02);
|
filter: saturate(1.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,8 +221,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-ghost-btn:hover {
|
.budget-ghost-btn:hover {
|
||||||
border-color: rgba(16, 185, 129, .32);
|
border-color: rgba(var(--theme-primary-rgb), .32);
|
||||||
color: #0f9f78;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,8 +310,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.department-list button.active {
|
.department-list button.active {
|
||||||
background: #e9f7f1;
|
background: var(--theme-primary-soft);
|
||||||
color: #07965f;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-table-wrap {
|
.budget-table-wrap {
|
||||||
@@ -392,24 +372,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-rate em.ok {
|
.budget-rate em.ok {
|
||||||
background: #13a66b;
|
background: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-rate em.warn {
|
.budget-rate em.warn {
|
||||||
background: #f2a51a;
|
background: var(--warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-rate em.danger {
|
.budget-rate em.danger {
|
||||||
background: #ef4444;
|
background: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-warning-red {
|
.budget-warning-red {
|
||||||
color: #e24b4b !important;
|
color: var(--danger) !important;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-warning-yellow {
|
.budget-warning-yellow {
|
||||||
color: #e3a008 !important;
|
color: var(--warning-active) !important;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,7 +403,7 @@
|
|||||||
.budget-row-actions button {
|
.budget-row-actions button {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #1c7ed6;
|
color: var(--theme-primary-active);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -467,14 +447,14 @@
|
|||||||
|
|
||||||
.budget-pager button:hover:not(.active):not(:disabled) {
|
.budget-pager button:hover:not(.active):not(:disabled) {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-pager button.active {
|
.budget-pager button.active {
|
||||||
background: #059669;
|
background: var(--theme-primary-active);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 16px rgba(5, 150, 105, .20);
|
box-shadow: 0 8px 16px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-pager button:disabled {
|
.budget-pager button:disabled {
|
||||||
@@ -502,19 +482,8 @@
|
|||||||
transition: border-color 160ms ease, color 160ms ease;
|
transition: border-color 160ms ease, color 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-page-size:hover {
|
.budget-page-size-select {
|
||||||
border-color: rgba(16, 185, 129, .32);
|
width: 112px;
|
||||||
color: #0f9f78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.budget-page-size select {
|
|
||||||
appearance: none;
|
|
||||||
border: 0;
|
|
||||||
background: transparent;
|
|
||||||
color: inherit;
|
|
||||||
font: inherit;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-bottom-grid {
|
.budget-bottom-grid {
|
||||||
@@ -526,7 +495,7 @@
|
|||||||
.budget-card-head button {
|
.budget-card-head button {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #1c7ed6;
|
color: var(--theme-primary-active);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -549,11 +518,11 @@
|
|||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: #13a66b;
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.legend-line.occupied {
|
.legend-line.occupied {
|
||||||
background: #f59e0b;
|
background: var(--warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
.legend-line.available {
|
.legend-line.available {
|
||||||
@@ -587,11 +556,11 @@
|
|||||||
.budget-alert-empty-icon {
|
.budget-alert-empty-icon {
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
border-radius: 12px;
|
border-radius: 8px;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
background: #e9f7f1;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,15 +598,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-alert-row i.danger {
|
.budget-alert-row i.danger {
|
||||||
background: #ef4444;
|
background: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-alert-row i.warn {
|
.budget-alert-row i.warn {
|
||||||
background: #f59e0b;
|
background: var(--warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-alert-row i.ok {
|
.budget-alert-row i.ok {
|
||||||
background: #13a66b;
|
background: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.budget-alert-row strong {
|
.budget-alert-row strong {
|
||||||
@@ -718,7 +687,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.budget-filter-bar label,
|
.budget-filter-bar label,
|
||||||
.budget-filter-bar select,
|
.budget-filter-bar .enterprise-select,
|
||||||
.budget-filter-set,
|
.budget-filter-set,
|
||||||
.budget-action-set,
|
.budget-action-set,
|
||||||
.budget-primary-btn,
|
.budget-primary-btn,
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
.conversation-list, .info-panel { display: grid; grid-template-rows: auto minmax(0, 1fr); }
|
.conversation-list, .info-panel { display: grid; grid-template-rows: auto minmax(0, 1fr); }
|
||||||
.side-panel header, .info-panel header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
|
.side-panel header, .info-panel header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
|
||||||
.side-panel h3, .info-panel h3 { display: inline-flex; align-items: center; gap: 8px; color: #0f172a; font-size: 17px; font-weight: 850; }
|
.side-panel h3, .info-panel h3 { display: inline-flex; align-items: center; gap: 8px; color: #0f172a; font-size: 17px; font-weight: 850; }
|
||||||
.outline-action, .info-panel header button { height: 34px; display: inline-flex; align-items: center; gap: 6px; border: 1px solid #d8e3ed; border-radius: 8px; background: #fff; color: #0f9f78; font-size: 13px; font-weight: 750; white-space: nowrap; }
|
.outline-action, .info-panel header button { height: 34px; display: inline-flex; align-items: center; gap: 6px; border: 1px solid #d8e3ed; border-radius: 8px; background: #fff; color: var(--theme-primary-active); font-size: 13px; font-weight: 750; white-space: nowrap; }
|
||||||
.outline-action { padding: 0 12px; }
|
.outline-action { padding: 0 12px; }
|
||||||
.info-panel header button { border: 0; color: #64748b; }
|
.info-panel header button { border: 0; color: #64748b; }
|
||||||
.session-scroll, .top-question-list, .similar-scroll { min-height: 0; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #cbd5e1 transparent; }
|
.session-scroll, .top-question-list, .similar-scroll { min-height: 0; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #cbd5e1 transparent; }
|
||||||
.session-scroll { display: grid; align-content: start; gap: 4px; padding-right: 4px; }
|
.session-scroll { display: grid; align-content: start; gap: 4px; padding-right: 4px; }
|
||||||
.session-row { width: 100%; min-height: 48px; display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 0 10px; border: 0; border-radius: 8px; background: transparent; color: #334155; text-align: left; }
|
.session-row { width: 100%; min-height: 48px; display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 0 10px; border: 0; border-radius: 8px; background: transparent; color: #334155; text-align: left; }
|
||||||
.session-row.active, .session-row:hover { background: #eaf8f1; color: #0f8f68; }
|
.session-row.active, .session-row:hover { background: var(--theme-primary-light-9); color: var(--theme-primary-active); }
|
||||||
.session-row span { color: #10b981; }
|
.session-row span { color: var(--theme-primary); }
|
||||||
.session-row strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 700; }
|
.session-row strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 700; }
|
||||||
.session-row time { color: #94a3b8; font-size: 12px; }
|
.session-row time { color: #94a3b8; font-size: 12px; }
|
||||||
.chat-panel { height: 100%; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto; overflow: hidden; }
|
.chat-panel { height: 100%; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto; overflow: hidden; }
|
||||||
@@ -22,20 +22,20 @@
|
|||||||
.talk-row { display: grid; grid-template-columns: 38px minmax(0, 1fr); gap: 12px; align-items: start; }
|
.talk-row { display: grid; grid-template-columns: 38px minmax(0, 1fr); gap: 12px; align-items: start; }
|
||||||
.avatar { width: 36px; height: 36px; display: grid; place-items: center; border-radius: 999px; color: #fff; font-size: 15px; font-weight: 850; }
|
.avatar { width: 36px; height: 36px; display: grid; place-items: center; border-radius: 999px; color: #fff; font-size: 15px; font-weight: 850; }
|
||||||
.user-avatar { background: linear-gradient(135deg, #26364d, #61748a); }
|
.user-avatar { background: linear-gradient(135deg, #26364d, #61748a); }
|
||||||
.assistant-avatar { background: #10b981; font-size: 20px; }
|
.assistant-avatar { background: var(--theme-primary); font-size: 20px; }
|
||||||
.talk-content header { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
|
.talk-content header { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
|
||||||
.talk-content header strong { color: #334155; font-size: 14px; font-weight: 800; }
|
.talk-content header strong { color: #334155; font-size: 14px; font-weight: 800; }
|
||||||
.talk-content header time { color: #94a3b8; font-size: 12px; }
|
.talk-content header time { color: #94a3b8; font-size: 12px; }
|
||||||
.user-question { display: inline-block; margin: 0; padding: 9px 16px; border-radius: 8px; background: #e8f5ef; color: #334155; font-size: 14px; line-height: 1.5; }
|
.user-question { display: inline-block; margin: 0; padding: 9px 16px; border-radius: 8px; background: var(--theme-primary-light-9); color: #334155; font-size: 14px; line-height: 1.5; }
|
||||||
.answer-card, .agent-answer-markdown { max-width: 760px; border: 1px solid #dce5ef; border-radius: 10px; background: #fff; color: #334155; box-shadow: 0 8px 24px rgba(15, 23, 42, .04); }
|
.answer-card, .agent-answer-markdown { max-width: 760px; border: 1px solid #dce5ef; border-radius: 10px; background: #fff; color: #334155; box-shadow: 0 8px 24px rgba(15, 23, 42, .04); }
|
||||||
.answer-card { display: grid; gap: 10px; padding: 13px 18px; }
|
.answer-card { display: grid; gap: 10px; padding: 13px 18px; }
|
||||||
.answer-card.compact { gap: 10px; }
|
.answer-card.compact { gap: 10px; }
|
||||||
.answer-card h4 { margin: 0 0 5px; color: #10a272; font-size: 13px; font-weight: 850; }
|
.answer-card h4 { margin: 0 0 5px; color: var(--theme-primary-active); font-size: 13px; font-weight: 850; }
|
||||||
.answer-card p, .answer-card ul { margin: 0; font-size: 14px; line-height: 1.58; }
|
.answer-card p, .answer-card ul { margin: 0; font-size: 14px; line-height: 1.58; }
|
||||||
.answer-card ul { padding-left: 18px; }
|
.answer-card ul { padding-left: 18px; }
|
||||||
.answer-card footer { display: flex; align-items: center; justify-content: flex-end; gap: 10px; color: #64748b; font-size: 12px; }
|
.answer-card footer { display: flex; align-items: center; justify-content: flex-end; gap: 10px; color: #64748b; font-size: 12px; }
|
||||||
.answer-card footer button { width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 6px; background: transparent; color: #64748b; }
|
.answer-card footer button { width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 6px; background: transparent; color: #64748b; }
|
||||||
.answer-card footer button:hover { background: #f1f5f9; color: #0f9f78; }
|
.answer-card footer button:hover { background: #f1f5f9; color: var(--theme-primary-active); }
|
||||||
.agent-answer-content { max-width: 760px; display: grid; gap: 10px; }
|
.agent-answer-content { max-width: 760px; display: grid; gap: 10px; }
|
||||||
.agent-answer-markdown { padding: 12px 16px; overflow-x: auto; font-size: 14px; }
|
.agent-answer-markdown { padding: 12px 16px; overflow-x: auto; font-size: 14px; }
|
||||||
.agent-answer-markdown :deep(h1),
|
.agent-answer-markdown :deep(h1),
|
||||||
@@ -59,20 +59,20 @@
|
|||||||
.agent-answer-markdown :deep(li) { line-height: 1.65; }
|
.agent-answer-markdown :deep(li) { line-height: 1.65; }
|
||||||
.agent-answer-markdown :deep(ul),
|
.agent-answer-markdown :deep(ul),
|
||||||
.agent-answer-markdown :deep(ol) { padding-left: 22px; }
|
.agent-answer-markdown :deep(ol) { padding-left: 22px; }
|
||||||
.agent-answer-markdown :deep(blockquote) { padding: 10px 12px; border-left: 4px solid #86efac; border-radius: 0 10px 10px 0; background: #f0fdf4; color: #475569; }
|
.agent-answer-markdown :deep(blockquote) { padding: 10px 12px; border-left: 4px solid var(--theme-primary-soft-strong); border-radius: 0 10px 10px 0; background: var(--theme-primary-light-9); color: #475569; }
|
||||||
.agent-answer-markdown :deep(strong) { color: #0f172a; }
|
.agent-answer-markdown :deep(strong) { color: #0f172a; }
|
||||||
.agent-answer-markdown :deep(code) { padding: 2px 6px; border-radius: 6px; background: #e2e8f0; font-size: 12px; }
|
.agent-answer-markdown :deep(code) { padding: 2px 6px; border-radius: 6px; background: #e2e8f0; font-size: 12px; }
|
||||||
.agent-answer-markdown :deep(pre) { overflow-x: auto; padding: 12px; border-radius: 10px; background: #0f172a; color: #e2e8f0; }
|
.agent-answer-markdown :deep(pre) { overflow-x: auto; padding: 12px; border-radius: 10px; background: #0f172a; color: #e2e8f0; }
|
||||||
.agent-answer-markdown :deep(pre code) { padding: 0; background: transparent; color: inherit; }
|
.agent-answer-markdown :deep(pre code) { padding: 0; background: transparent; color: inherit; }
|
||||||
.agent-answer-markdown :deep(a) { color: #059669; text-decoration: underline; }
|
.agent-answer-markdown :deep(a) { color: var(--theme-primary-active); text-decoration: underline; }
|
||||||
.agent-answer-markdown :deep(table) { width: auto; max-width: 100%; border: 1px solid #dce5ef; border-radius: 10px; border-collapse: collapse; background: #fff; box-shadow: 0 8px 24px rgba(15, 23, 42, .04); font-size: 13px; }
|
.agent-answer-markdown :deep(table) { width: auto; max-width: 100%; border: 1px solid #dce5ef; border-radius: 10px; border-collapse: collapse; background: #fff; box-shadow: 0 8px 24px rgba(15, 23, 42, .04); font-size: 13px; }
|
||||||
.agent-answer-markdown :deep(th),
|
.agent-answer-markdown :deep(th),
|
||||||
.agent-answer-markdown :deep(td) { padding: 10px 12px; border-bottom: 1px solid #e2e8f0; text-align: left; white-space: nowrap; }
|
.agent-answer-markdown :deep(td) { padding: 10px 12px; border-bottom: 1px solid #e2e8f0; text-align: left; white-space: nowrap; }
|
||||||
.agent-answer-markdown :deep(th) { background: #eef7f2; color: #0f172a; font-weight: 800; }
|
.agent-answer-markdown :deep(th) { background: var(--theme-primary-light-9); color: #0f172a; font-weight: 800; }
|
||||||
.agent-answer-markdown :deep(td) { color: #334155; font-weight: 650; }
|
.agent-answer-markdown :deep(td) { color: #334155; font-weight: 650; }
|
||||||
.agent-answer-markdown :deep(tbody tr:last-child td) { border-bottom: 0; }
|
.agent-answer-markdown :deep(tbody tr:last-child td) { border-bottom: 0; }
|
||||||
.agent-meta-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; max-width: 760px; }
|
.agent-meta-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; max-width: 760px; }
|
||||||
.agent-meta-chip { min-height: 26px; display: inline-flex; align-items: center; padding: 0 10px; border-radius: 999px; background: #eef7f2; color: #0f766e; font-size: 12px; font-weight: 760; }
|
.agent-meta-chip { min-height: 26px; display: inline-flex; align-items: center; padding: 0 10px; border-radius: 999px; background: var(--theme-primary-light-9); color: var(--theme-primary-active); font-size: 12px; font-weight: 760; }
|
||||||
.agent-detail-block { max-width: 760px; margin-top: 10px; display: grid; gap: 8px; }
|
.agent-detail-block { max-width: 760px; margin-top: 10px; display: grid; gap: 8px; }
|
||||||
.agent-detail-block > strong { color: #0f172a; font-size: 12px; font-weight: 820; }
|
.agent-detail-block > strong { color: #0f172a; font-size: 12px; font-weight: 820; }
|
||||||
.agent-citation-disclosure { overflow: hidden; border: 1px solid #dce5ef; border-radius: 10px; background: #fff; }
|
.agent-citation-disclosure { overflow: hidden; border: 1px solid #dce5ef; border-radius: 10px; background: #fff; }
|
||||||
@@ -103,22 +103,22 @@
|
|||||||
.prompt-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; overflow-x: auto; }
|
.prompt-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; overflow-x: auto; }
|
||||||
.prompt-toolbar span { flex: 0 0 auto; color: #64748b; font-size: 13px; font-weight: 800; }
|
.prompt-toolbar span { flex: 0 0 auto; color: #64748b; font-size: 13px; font-weight: 800; }
|
||||||
.prompt-toolbar button { height: 34px; flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px; padding: 0 14px; border: 1px solid #dce5ef; border-radius: 8px; background: #fff; color: #334155; font-size: 13px; font-weight: 750; }
|
.prompt-toolbar button { height: 34px; flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px; padding: 0 14px; border: 1px solid #dce5ef; border-radius: 8px; background: #fff; color: #334155; font-size: 13px; font-weight: 750; }
|
||||||
.prompt-toolbar button i { color: #10b981; }
|
.prompt-toolbar button i { color: var(--theme-primary); }
|
||||||
.prompt-toolbar .icon-refresh { width: 34px; padding: 0; justify-content: center; }
|
.prompt-toolbar .icon-refresh { width: 34px; padding: 0; justify-content: center; }
|
||||||
.composer { min-height: 64px; display: grid; grid-template-columns: minmax(0, 1fr) 48px; align-items: center; gap: 10px; padding: 8px; border: 1px solid #cbd8e5; border-radius: 8px; background: linear-gradient(180deg, #fff, #fbfdff); box-shadow: 0 1px 2px rgba(15, 23, 42, .04); transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease; }
|
.composer { min-height: 64px; display: grid; grid-template-columns: minmax(0, 1fr) 48px; align-items: center; gap: 10px; padding: 8px; border: 1px solid #cbd8e5; border-radius: 8px; background: linear-gradient(180deg, #fff, #fbfdff); box-shadow: 0 1px 2px rgba(15, 23, 42, .04); transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease; }
|
||||||
.composer:focus-within { border-color: rgba(16, 185, 129, .58); background: #fff; box-shadow: 0 0 0 3px rgba(16, 185, 129, .11), 0 10px 24px rgba(15, 23, 42, .06); }
|
.composer:focus-within { border-color: rgba(var(--theme-primary-rgb), .58); background: #fff; box-shadow: 0 0 0 3px var(--theme-focus-ring), 0 10px 24px rgba(15, 23, 42, .06); }
|
||||||
.composer textarea { height: 48px; min-height: 48px; resize: none; border: 0; padding: 5px 8px; background: transparent; color: #0f172a; font-size: 14px; line-height: 1.55; }
|
.composer textarea { height: 48px; min-height: 48px; resize: none; border: 0; padding: 5px 8px; background: transparent; color: #0f172a; font-size: 14px; line-height: 1.55; }
|
||||||
.composer textarea::placeholder { color: #94a3b8; }
|
.composer textarea::placeholder { color: #94a3b8; }
|
||||||
.composer textarea:focus { outline: none; }
|
.composer textarea:focus { outline: none; }
|
||||||
.send-button { width: 48px; height: 48px; display: grid; place-items: center; border: 0; border-radius: 8px; background: #10b981; color: #fff; font-size: 20px; box-shadow: 0 8px 18px rgba(16, 185, 129, .20); transition: background 160ms ease, transform 160ms ease, box-shadow 160ms ease; }
|
.send-button { width: 48px; height: 48px; display: grid; place-items: center; border: 0; border-radius: 8px; background: var(--theme-primary); color: #fff; font-size: 20px; box-shadow: 0 8px 18px var(--theme-primary-shadow); transition: background 160ms ease, transform 160ms ease, box-shadow 160ms ease; }
|
||||||
.send-button:hover { background: #0ea672; box-shadow: 0 10px 22px rgba(16, 185, 129, .24); }
|
.send-button:hover { background: var(--theme-primary-hover); box-shadow: 0 10px 22px rgba(var(--theme-primary-rgb), .24); }
|
||||||
.send-button:active { transform: scale(.96); }
|
.send-button:active { transform: scale(.96); }
|
||||||
.send-button:disabled { background: #94a3b8; box-shadow: none; transform: none; }
|
.send-button:disabled { background: #94a3b8; box-shadow: none; transform: none; }
|
||||||
.hot-top-panel h3 i { color: #ef4444; }
|
.hot-top-panel h3 i { color: #ef4444; }
|
||||||
.top-question-list { display: grid; align-content: start; gap: 8px; padding-right: 4px; }
|
.top-question-list { display: grid; align-content: start; gap: 8px; padding-right: 4px; }
|
||||||
.top-question-list button { min-height: 42px; display: grid; grid-template-columns: 34px minmax(0, 1fr) 14px; align-items: center; gap: 10px; padding: 0 8px; border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; color: #334155; text-align: left; }
|
.top-question-list button { min-height: 42px; display: grid; grid-template-columns: 34px minmax(0, 1fr) 14px; align-items: center; gap: 10px; padding: 0 8px; border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; color: #334155; text-align: left; }
|
||||||
.top-question-list button:hover { border-color: rgba(16, 185, 129, .32); color: #0f9f78; }
|
.top-question-list button:hover { border-color: rgba(var(--theme-primary-rgb), .32); color: var(--theme-primary-active); }
|
||||||
.top-question-list strong { color: #10b981; font-size: 13px; font-weight: 850; font-variant-numeric: tabular-nums; }
|
.top-question-list strong { color: var(--theme-primary); font-size: 13px; font-weight: 850; font-variant-numeric: tabular-nums; }
|
||||||
.top-question-list span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 750; }
|
.top-question-list span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 750; }
|
||||||
.top-question-list i { color: #94a3b8; }
|
.top-question-list i { color: #94a3b8; }
|
||||||
.similar-panel { display: grid; }
|
.similar-panel { display: grid; }
|
||||||
@@ -127,19 +127,19 @@
|
|||||||
.similar-row:first-child { border-top: 0; }
|
.similar-row:first-child { border-top: 0; }
|
||||||
.similar-row span { min-width: 0; display: inline-flex; align-items: center; gap: 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 700; }
|
.similar-row span { min-width: 0; display: inline-flex; align-items: center; gap: 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 700; }
|
||||||
.similar-row span i { color: #64748b; font-size: 17px; }
|
.similar-row span i { color: #64748b; font-size: 17px; }
|
||||||
.similar-row strong { height: 26px; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; background: #e8f8f0; color: #15945f; font-size: 13px; font-weight: 850; }
|
.similar-row strong { height: 26px; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; background: var(--theme-primary-light-9); color: var(--theme-primary-active); font-size: 13px; font-weight: 850; }
|
||||||
.similar-row > i { color: #94a3b8; }
|
.similar-row > i { color: #94a3b8; }
|
||||||
.semantic-debug-panel { display: grid; grid-template-rows: auto minmax(0, 1fr); }
|
.semantic-debug-panel { display: grid; grid-template-rows: auto minmax(0, 1fr); }
|
||||||
.semantic-debug-body { min-height: 0; display: grid; grid-template-rows: auto auto auto auto minmax(0, 1fr); gap: 12px; }
|
.semantic-debug-body { min-height: 0; display: grid; grid-template-rows: auto auto auto auto minmax(0, 1fr); gap: 12px; }
|
||||||
.semantic-debug-input { display: grid; gap: 8px; }
|
.semantic-debug-input { display: grid; gap: 8px; }
|
||||||
.semantic-debug-input span { color: #334155; font-size: 13px; font-weight: 800; }
|
.semantic-debug-input span { color: #334155; font-size: 13px; font-weight: 800; }
|
||||||
.semantic-debug-input textarea { min-height: 98px; resize: vertical; padding: 12px 13px; border: 1px solid #d7e0ea; border-radius: 10px; background: linear-gradient(180deg, #ffffff, #f7fbff); color: #0f172a; font-size: 13px; line-height: 1.6; }
|
.semantic-debug-input textarea { min-height: 98px; resize: vertical; padding: 12px 13px; border: 1px solid #d7e0ea; border-radius: 10px; background: linear-gradient(180deg, #ffffff, #f7fbff); color: #0f172a; font-size: 13px; line-height: 1.6; }
|
||||||
.semantic-debug-input textarea:focus { outline: none; border-color: rgba(16, 185, 129, .48); box-shadow: 0 0 0 3px rgba(16, 185, 129, .11); }
|
.semantic-debug-input textarea:focus { outline: none; border-color: rgba(var(--theme-primary-rgb), .48); box-shadow: 0 0 0 3px var(--theme-focus-ring); }
|
||||||
.semantic-debug-actions { display: flex; flex-wrap: wrap; gap: 8px; }
|
.semantic-debug-actions { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||||
.semantic-chip { min-height: 30px; padding: 0 10px; border: 1px solid #d8e3ed; border-radius: 999px; background: #f8fbff; color: #334155; font-size: 12px; font-weight: 760; text-align: left; }
|
.semantic-chip { min-height: 30px; padding: 0 10px; border: 1px solid #d8e3ed; border-radius: 999px; background: #f8fbff; color: #334155; font-size: 12px; font-weight: 760; text-align: left; }
|
||||||
.semantic-chip:hover { border-color: rgba(16, 185, 129, .32); background: #eefbf5; color: #0f8f68; }
|
.semantic-chip:hover { border-color: rgba(var(--theme-primary-rgb), .32); background: var(--theme-primary-light-9); color: var(--theme-primary-active); }
|
||||||
.semantic-debug-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
.semantic-debug-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
||||||
.semantic-parse-btn { min-height: 36px; display: inline-flex; align-items: center; gap: 8px; padding: 0 14px; border: 0; border-radius: 9px; background: linear-gradient(135deg, #0f766e, #10b981); color: #fff; font-size: 13px; font-weight: 800; box-shadow: 0 10px 20px rgba(16, 185, 129, .18); }
|
.semantic-parse-btn { min-height: 36px; display: inline-flex; align-items: center; gap: 8px; padding: 0 14px; border: 0; border-radius: 9px; background: var(--theme-gradient-primary); color: #fff; font-size: 13px; font-weight: 800; box-shadow: 0 10px 20px var(--theme-primary-shadow); }
|
||||||
.semantic-parse-btn:disabled { background: #cbd5e1; box-shadow: none; }
|
.semantic-parse-btn:disabled { background: #cbd5e1; box-shadow: none; }
|
||||||
.semantic-inline-meta { color: #64748b; font-size: 12px; }
|
.semantic-inline-meta { color: #64748b; font-size: 12px; }
|
||||||
.semantic-debug-error { margin: 0; padding: 10px 12px; border-radius: 10px; background: #fff1f2; color: #be123c; font-size: 12px; line-height: 1.55; }
|
.semantic-debug-error { margin: 0; padding: 10px 12px; border-radius: 10px; background: #fff1f2; color: #be123c; font-size: 12px; line-height: 1.55; }
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
.semantic-result-card strong { color: #0f172a; font-size: 14px; font-weight: 850; word-break: break-word; }
|
.semantic-result-card strong { color: #0f172a; font-size: 14px; font-weight: 850; word-break: break-word; }
|
||||||
.semantic-field-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
|
.semantic-field-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
|
||||||
.semantic-field-list section { min-height: 72px; padding: 12px; border-radius: 10px; background: #f8fafc; }
|
.semantic-field-list section { min-height: 72px; padding: 12px; border-radius: 10px; background: #f8fafc; }
|
||||||
.semantic-field-list h4, .semantic-json-block h4 { margin: 0 0 6px; color: #0f766e; font-size: 12px; font-weight: 850; letter-spacing: .02em; }
|
.semantic-field-list h4, .semantic-json-block h4 { margin: 0 0 6px; color: var(--theme-primary-active); font-size: 12px; font-weight: 850; letter-spacing: .02em; }
|
||||||
.semantic-field-list p { margin: 0; color: #334155; font-size: 12px; line-height: 1.6; word-break: break-word; }
|
.semantic-field-list p { margin: 0; color: #334155; font-size: 12px; line-height: 1.6; word-break: break-word; }
|
||||||
.semantic-json-block { min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); overflow: hidden; }
|
.semantic-json-block { min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); overflow: hidden; }
|
||||||
.semantic-json-block pre { min-height: 0; margin: 0; padding: 12px; overflow: auto; border-radius: 10px; background: #0f172a; color: #d7f7ea; font-size: 11px; line-height: 1.55; }
|
.semantic-json-block pre { min-height: 0; margin: 0; padding: 12px; overflow: auto; border-radius: 10px; background: #0f172a; color: #d7f7ea; font-size: 11px; line-height: 1.55; }
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active {
|
.status-tabs button.active {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active::after {
|
.status-tabs button.active::after {
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
bottom: -1px;
|
bottom: -1px;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
border-radius: 999px 999px 0 0;
|
border-radius: 999px 999px 0 0;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.scope-tab-badge {
|
.scope-tab-badge {
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
height: 38px;
|
height: 38px;
|
||||||
padding: 0 12px 0 36px;
|
padding: 0 12px 0 36px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -113,13 +113,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.list-search input:focus {
|
.list-search input:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.14);
|
box-shadow: 0 0 0 3px rgba(58, 124, 165, 0.14);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-btn,
|
.filter-btn {
|
||||||
.page-size {
|
|
||||||
min-height: 38px;
|
min-height: 38px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -127,7 +126,7 @@
|
|||||||
gap: 9px;
|
gap: 9px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -140,10 +139,9 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-btn:hover,
|
.filter-btn:hover {
|
||||||
.page-size:hover {
|
border-color: rgba(58, 124, 165, .32);
|
||||||
border-color: rgba(16, 185, 129, .32);
|
color: var(--theme-primary-active);
|
||||||
color: #0f9f78;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-filter,
|
.document-filter,
|
||||||
@@ -152,12 +150,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.document-filter-menu,
|
.document-filter-menu,
|
||||||
.date-range-popover,
|
.date-range-popover {
|
||||||
.page-size-dropdown {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 40;
|
z-index: 40;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 10px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 16px 32px rgba(15, 23, 42, 0.12);
|
box-shadow: 0 16px 32px rgba(15, 23, 42, 0.12);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -172,14 +169,13 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-filter-menu button,
|
.document-filter-menu button {
|
||||||
.page-size-dropdown button {
|
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 36px;
|
min-height: 36px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -190,8 +186,8 @@
|
|||||||
|
|
||||||
.document-filter-menu button:hover,
|
.document-filter-menu button:hover,
|
||||||
.document-filter-menu button.active {
|
.document-filter-menu button.active {
|
||||||
background: rgba(16, 185, 129, 0.1);
|
background: rgba(58, 124, 165, 0.1);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.date-range-trigger {
|
.date-range-trigger {
|
||||||
@@ -233,7 +229,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
@@ -260,7 +256,7 @@
|
|||||||
height: 38px;
|
height: 38px;
|
||||||
padding: 0 9px;
|
padding: 0 9px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
@@ -269,7 +265,7 @@
|
|||||||
.apply-btn {
|
.apply-btn {
|
||||||
height: 36px;
|
height: 36px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 750;
|
font-weight: 750;
|
||||||
}
|
}
|
||||||
@@ -282,7 +278,7 @@
|
|||||||
|
|
||||||
.apply-btn {
|
.apply-btn {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,12 +296,12 @@
|
|||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
box-shadow: 0 10px 24px rgba(5, 150, 105, 0.2);
|
box-shadow: 0 10px 24px var(--theme-primary-shadow);
|
||||||
transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
|
transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,13 +314,13 @@
|
|||||||
|
|
||||||
.create-request-btn:hover {
|
.create-request-btn:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 0 14px 28px rgba(5, 150, 105, 0.24);
|
box-shadow: 0 14px 28px var(--theme-primary-shadow);
|
||||||
filter: saturate(1.02);
|
filter: saturate(1.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-request-btn.secondary:hover {
|
.create-request-btn.secondary:hover {
|
||||||
border-color: rgba(16, 185, 129, .32);
|
border-color: rgba(58, 124, 165, .32);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.08);
|
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +341,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-filter-trigger > .mdi:first-child {
|
.status-filter-trigger > .mdi:first-child {
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-filter-menu {
|
.status-filter-menu {
|
||||||
@@ -388,7 +384,7 @@
|
|||||||
|
|
||||||
.table-state .mdi {
|
.table-state .mdi {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-state strong {
|
.table-state strong {
|
||||||
@@ -469,7 +465,7 @@ tbody tr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tbody tr:hover {
|
tbody tr:hover {
|
||||||
background: linear-gradient(90deg, rgba(16, 185, 129, .08), rgba(16, 185, 129, .03));
|
background: linear-gradient(90deg, rgba(58, 124, 165, .08), rgba(58, 124, 165, .03));
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody tr:last-child td {
|
tbody tr:last-child td {
|
||||||
@@ -477,7 +473,7 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.doc-id {
|
.doc-id {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,8 +522,8 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.doc-kind-tag.reimbursement {
|
.doc-kind-tag.reimbursement {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-light-9);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-kind-tag.application {
|
.doc-kind-tag.application {
|
||||||
@@ -546,8 +542,8 @@ tbody tr:last-child td {
|
|||||||
.type-tag.travel,
|
.type-tag.travel,
|
||||||
.type-tag.hotel,
|
.type-tag.hotel,
|
||||||
.type-tag.transport {
|
.type-tag.transport {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-light-9);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.type-tag.entertainment,
|
.type-tag.entertainment,
|
||||||
@@ -589,9 +585,9 @@ tbody tr:last-child td {
|
|||||||
|
|
||||||
.status-tag.success,
|
.status-tag.success,
|
||||||
.status-tag.archived {
|
.status-tag.archived {
|
||||||
border-color: #bbf7d0;
|
border-color: var(--success-line);
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tag.warning,
|
.status-tag.warning,
|
||||||
@@ -650,14 +646,14 @@ tbody tr:last-child td {
|
|||||||
|
|
||||||
.pager button:hover:not(.active) {
|
.pager button:hover:not(.active) {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pager button.active {
|
.pager button.active {
|
||||||
background: #059669;
|
background: var(--theme-primary-active);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 16px rgba(5, 150, 105, .20);
|
box-shadow: 0 8px 16px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pager button:disabled {
|
.pager button:disabled {
|
||||||
@@ -665,40 +661,11 @@ tbody tr:last-child td {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size-wrap {
|
.page-size-select {
|
||||||
position: relative;
|
width: 118px;
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size {
|
|
||||||
min-width: 112px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown {
|
|
||||||
right: 0;
|
|
||||||
bottom: calc(100% + 6px);
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button {
|
|
||||||
border-radius: 0;
|
|
||||||
text-align: center;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button:hover {
|
|
||||||
background: #f0fdf4;
|
|
||||||
color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button.active {
|
|
||||||
background: #059669;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
.document-toolbar,
|
.document-toolbar,
|
||||||
.list-foot {
|
.list-foot {
|
||||||
@@ -730,7 +697,7 @@ tbody tr:last-child td {
|
|||||||
.document-status-filter,
|
.document-status-filter,
|
||||||
.list-search,
|
.list-search,
|
||||||
.filter-btn,
|
.filter-btn,
|
||||||
.page-size {
|
.page-size-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active {
|
.status-tabs button.active {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active::after {
|
.status-tabs button.active::after {
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
bottom: -1px;
|
bottom: -1px;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
border-radius: 999px 999px 0 0;
|
border-radius: 999px 999px 0 0;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button small {
|
.status-tabs button small {
|
||||||
@@ -84,8 +84,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active small {
|
.status-tabs button.active small {
|
||||||
background: rgba(16, 185, 129, 0.12);
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-toolbar {
|
.list-toolbar {
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
height: 38px;
|
height: 38px;
|
||||||
padding: 0 12px 0 36px;
|
padding: 0 12px 0 36px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -136,8 +136,8 @@
|
|||||||
|
|
||||||
.list-search input:focus {
|
.list-search input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: rgba(16, 185, 129, 0.6);
|
border-color: rgba(var(--theme-primary-rgb), 0.6);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-trigger,
|
.picker-trigger,
|
||||||
@@ -147,7 +147,7 @@
|
|||||||
.create-btn,
|
.create-btn,
|
||||||
.row-action {
|
.row-action {
|
||||||
min-height: 38px;
|
min-height: 38px;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 750;
|
font-weight: 750;
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
gap: 9px;
|
gap: 9px;
|
||||||
padding: 0 34px 0 12px;
|
padding: 0 34px 0 12px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -187,9 +187,9 @@
|
|||||||
|
|
||||||
.picker-trigger:hover,
|
.picker-trigger:hover,
|
||||||
.picker-filter.open .picker-trigger {
|
.picker-filter.open .picker-trigger {
|
||||||
border-color: rgba(16, 185, 129, 0.34);
|
border-color: rgba(var(--theme-primary-rgb), 0.34);
|
||||||
background: #f6fffb;
|
background: var(--theme-primary-soft);
|
||||||
color: #0f9f78;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-actions {
|
.toolbar-actions {
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 18px 42px rgba(15, 23, 42, 0.16);
|
box-shadow: 0 18px 42px rgba(15, 23, 42, 0.16);
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border: 1px solid #d7e0ea;
|
border: 1px solid #d7e0ea;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -263,14 +263,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.picker-option:hover {
|
.picker-option:hover {
|
||||||
border-color: rgba(16, 185, 129, 0.28);
|
border-color: rgba(var(--theme-primary-rgb), 0.28);
|
||||||
background: #f0fdf4;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-option.active {
|
.picker-option.active {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,9 +279,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 7px;
|
gap: 7px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 1px solid rgba(5, 150, 105, 0.16);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.18);
|
||||||
background: #f8fffb;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.template-btn,
|
.template-btn,
|
||||||
@@ -297,9 +297,9 @@
|
|||||||
|
|
||||||
.template-btn:hover,
|
.template-btn:hover,
|
||||||
.export-btn:hover {
|
.export-btn:hover {
|
||||||
border-color: rgba(16, 185, 129, 0.34);
|
border-color: rgba(var(--theme-primary-rgb), 0.34);
|
||||||
background: #f6fffb;
|
background: var(--theme-primary-soft);
|
||||||
color: #0f9f78;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-btn {
|
.create-btn {
|
||||||
@@ -308,9 +308,9 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 18px rgba(5, 150, 105, 0.18);
|
box-shadow: 0 8px 18px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-btn:disabled,
|
.create-btn:disabled,
|
||||||
@@ -445,86 +445,25 @@
|
|||||||
|
|
||||||
.pager button:hover:not(.active) {
|
.pager button:hover:not(.active) {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pager button.active {
|
.pager button.active {
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 16px rgba(5, 150, 105, 0.2);
|
box-shadow: 0 8px 16px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-nav {
|
.page-nav {
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size {
|
.page-size-select {
|
||||||
min-height: 38px;
|
width: 112px;
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 9px;
|
|
||||||
min-width: 112px;
|
|
||||||
padding: 0 14px;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 750;
|
|
||||||
white-space: nowrap;
|
|
||||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size:hover {
|
|
||||||
border-color: rgba(16, 185, 129, 0.32);
|
|
||||||
color: #0f9f78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-wrap {
|
|
||||||
position: relative;
|
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size-dropdown {
|
|
||||||
position: absolute;
|
|
||||||
bottom: calc(100% + 6px);
|
|
||||||
right: 0;
|
|
||||||
z-index: 40;
|
|
||||||
display: grid;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.14);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button {
|
|
||||||
height: 36px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
background: transparent;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 750;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 0 20px;
|
|
||||||
transition: background 120ms ease, color 120ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button:hover {
|
|
||||||
background: #f0fdf4;
|
|
||||||
color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button.active {
|
|
||||||
background: #059669;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-state {
|
.table-state {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 220px;
|
min-height: 220px;
|
||||||
@@ -539,7 +478,7 @@
|
|||||||
|
|
||||||
.table-state i {
|
.table-state i {
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-state.error i {
|
.table-state.error i {
|
||||||
@@ -559,10 +498,10 @@
|
|||||||
.state-action {
|
.state-action {
|
||||||
min-height: 36px;
|
min-height: 36px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 1px solid rgba(5, 150, 105, 0.22);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.22);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 760;
|
font-weight: 760;
|
||||||
}
|
}
|
||||||
@@ -644,7 +583,7 @@ tbody tr:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tbody tr.spotlight {
|
tbody tr.spotlight {
|
||||||
background: linear-gradient(90deg, rgba(16, 185, 129, 0.05), rgba(59, 130, 246, 0.03));
|
background: linear-gradient(90deg, rgba(var(--theme-primary-rgb), 0.05), rgba(var(--theme-primary-rgb), 0.02));
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody tr:last-child td {
|
tbody tr:last-child td {
|
||||||
@@ -665,7 +604,7 @@ tbody tr:last-child td {
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 11px;
|
border-radius: 11px;
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: var(--theme-gradient-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
@@ -709,8 +648,8 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.success {
|
.status-pill.success {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.warning {
|
.status-pill.warning {
|
||||||
@@ -733,8 +672,8 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.role-pill {
|
.role-pill {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.more-pill {
|
.more-pill {
|
||||||
@@ -744,9 +683,9 @@ tbody tr:last-child td {
|
|||||||
|
|
||||||
.row-action {
|
.row-action {
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.32);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.32);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-scroll {
|
.detail-scroll {
|
||||||
@@ -774,7 +713,7 @@ tbody tr:last-child td {
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
background: linear-gradient(135deg, #10b981, #047857);
|
background: var(--theme-gradient-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
@@ -950,8 +889,8 @@ tbody tr:last-child td {
|
|||||||
|
|
||||||
.manager-picker.open .manager-picker-trigger,
|
.manager-picker.open .manager-picker-trigger,
|
||||||
.manager-picker-trigger:hover {
|
.manager-picker-trigger:hover {
|
||||||
border-color: rgba(16, 185, 129, 0.34);
|
border-color: rgba(var(--theme-primary-rgb), 0.34);
|
||||||
background: #f6fffb;
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.manager-picker-label {
|
.manager-picker-label {
|
||||||
@@ -987,8 +926,8 @@ tbody tr:last-child td {
|
|||||||
|
|
||||||
.manager-picker-panel input[type='search']:focus {
|
.manager-picker-panel input[type='search']:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: rgba(16, 185, 129, 0.6);
|
border-color: rgba(var(--theme-primary-rgb), 0.6);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.manager-picker-options {
|
.manager-picker-options {
|
||||||
@@ -1022,8 +961,8 @@ tbody tr:last-child td {
|
|||||||
|
|
||||||
.manager-picker-option:hover,
|
.manager-picker-option:hover,
|
||||||
.manager-picker-option.active {
|
.manager-picker-option.active {
|
||||||
border-color: rgba(16, 185, 129, 0.32);
|
border-color: rgba(var(--theme-primary-rgb), 0.32);
|
||||||
background: linear-gradient(180deg, rgba(240, 253, 244, 0.85), #ffffff);
|
background: linear-gradient(180deg, var(--theme-primary-soft), #ffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
.manager-picker-empty {
|
.manager-picker-empty {
|
||||||
@@ -1051,8 +990,8 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.role-card.active {
|
.role-card.active {
|
||||||
border-color: rgba(16, 185, 129, 0.32);
|
border-color: rgba(var(--theme-primary-rgb), 0.32);
|
||||||
background: linear-gradient(180deg, rgba(240, 253, 244, 0.85), #ffffff);
|
background: linear-gradient(180deg, var(--theme-primary-soft), #ffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
.role-card input {
|
.role-card input {
|
||||||
@@ -1174,7 +1113,7 @@ td.cell-updated {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.publish-summary strong {
|
.publish-summary strong {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
@@ -1221,10 +1160,10 @@ td.cell-updated {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.major-action {
|
.major-action {
|
||||||
border: 1px solid #059669;
|
border: 1px solid var(--theme-primary);
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 4px 12px rgba(5, 150, 105, 0.16);
|
box-shadow: 0 4px 12px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.minor-action:disabled,
|
.minor-action:disabled,
|
||||||
@@ -1286,7 +1225,7 @@ td.cell-updated {
|
|||||||
width: min(280px, calc(100vw - 64px));
|
width: min(280px, calc(100vw - 64px));
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size,
|
.page-size-select,
|
||||||
.pager {
|
.pager {
|
||||||
justify-self: stretch;
|
justify-self: stretch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detail-state i {
|
.detail-state i {
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,8 +212,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.trace-step.active {
|
.trace-step.active {
|
||||||
border-color: rgba(16, 185, 129, 0.32);
|
border-color: rgba(var(--theme-primary-rgb), 0.32);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.08);
|
box-shadow: 0 0 0 3px rgba(var(--theme-primary-rgb), 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-index {
|
.step-index {
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ecfeff;
|
background: #ecfeff;
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -287,8 +287,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.success {
|
.status-pill.success {
|
||||||
background: rgba(22, 163, 74, 0.12);
|
background: rgba(var(--success-rgb), 0.12);
|
||||||
color: #166534;
|
color: var(--success-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.warning,
|
.status-pill.warning,
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
padding: 48px clamp(40px, 5vw, 86px);
|
padding: 48px clamp(40px, 5vw, 86px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background:
|
background:
|
||||||
linear-gradient(120deg, rgba(236,253,245,.72), transparent 34%),
|
linear-gradient(120deg, rgba(var(--theme-primary-rgb, 58, 124, 165), .10), transparent 34%),
|
||||||
linear-gradient(105deg, #f8fafc 0%, #f4fbf8 44%, #f8fafc 100%);
|
linear-gradient(105deg, #f8fafc 0%, #f5faff 44%, #f8fafc 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-page::before {
|
.login-page::before {
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
background:
|
background:
|
||||||
linear-gradient(90deg, rgba(15,23,42,.045) 1px, transparent 1px),
|
linear-gradient(90deg, rgba(15,23,42,.045) 1px, transparent 1px),
|
||||||
linear-gradient(0deg, rgba(15,23,42,.04) 1px, transparent 1px),
|
linear-gradient(0deg, rgba(15,23,42,.04) 1px, transparent 1px),
|
||||||
radial-gradient(circle at 28% 72%, rgba(16,185,129,.12), transparent 28%),
|
radial-gradient(circle at 28% 72%, rgba(var(--theme-primary-rgb, 58, 124, 165), .10), transparent 28%),
|
||||||
radial-gradient(circle at 75% 22%, rgba(245,158,11,.08), transparent 30%);
|
radial-gradient(circle at 75% 22%, rgba(37,99,235,.06), transparent 30%);
|
||||||
background-size: 72px 72px, 72px 72px, auto, auto;
|
background-size: 72px 72px, 72px 72px, auto, auto;
|
||||||
mask-image: linear-gradient(100deg, rgba(0,0,0,.7), rgba(0,0,0,.32) 48%, rgba(0,0,0,.16));
|
mask-image: linear-gradient(100deg, rgba(0,0,0,.7), rgba(0,0,0,.32) 48%, rgba(0,0,0,.16));
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@@ -37,11 +37,11 @@
|
|||||||
width: min(820px, 58vw);
|
width: min(820px, 58vw);
|
||||||
height: min(560px, 64vh);
|
height: min(560px, 64vh);
|
||||||
border: 1px solid rgba(148,163,184,.22);
|
border: 1px solid rgba(148,163,184,.22);
|
||||||
border-radius: 18px;
|
border-radius: 8px;
|
||||||
background:
|
background:
|
||||||
linear-gradient(90deg, transparent 0 28%, rgba(15,23,42,.055) 28% calc(28% + 1px), transparent calc(28% + 1px)),
|
linear-gradient(90deg, transparent 0 28%, rgba(15,23,42,.055) 28% calc(28% + 1px), transparent calc(28% + 1px)),
|
||||||
repeating-linear-gradient(0deg, transparent 0 35px, rgba(15,23,42,.05) 36px),
|
repeating-linear-gradient(0deg, transparent 0 35px, rgba(15,23,42,.05) 36px),
|
||||||
linear-gradient(135deg, rgba(255,255,255,.74), rgba(236,253,245,.32));
|
linear-gradient(135deg, rgba(255,255,255,.74), rgba(var(--theme-primary-rgb, 58, 124, 165), .10));
|
||||||
box-shadow: 0 34px 80px rgba(15,23,42,.08);
|
box-shadow: 0 34px 80px rgba(15,23,42,.08);
|
||||||
transform: rotate(-7deg);
|
transform: rotate(-7deg);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
height: 34px;
|
height: 34px;
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.logo-mark svg) {
|
:deep(.logo-mark svg) {
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.eyebrow-text {
|
.eyebrow-text {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
letter-spacing: .08em;
|
letter-spacing: .08em;
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
width: 230px;
|
width: 230px;
|
||||||
height: 62px;
|
height: 62px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: linear-gradient(90deg, rgba(16,185,129,.16), rgba(245,158,11,.12));
|
background: linear-gradient(90deg, rgba(var(--theme-primary-rgb, 58, 124, 165), .14), rgba(37,99,235,.08));
|
||||||
filter: blur(4px);
|
filter: blur(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,10 +139,10 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
display: block;
|
display: block;
|
||||||
border: 1px solid rgba(16,185,129,.18);
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), .22);
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
border-radius: 0 22px 0 0;
|
border-radius: 0 8px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flow-line::after {
|
.flow-line::after {
|
||||||
@@ -153,8 +153,8 @@
|
|||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 5px rgba(16,185,129,.12);
|
box-shadow: 0 0 0 5px rgba(var(--theme-primary-rgb, 58, 124, 165), .12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.flow-a {
|
.flow-a {
|
||||||
@@ -197,7 +197,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: 7px;
|
gap: 7px;
|
||||||
padding: 17px 18px;
|
padding: 17px 18px;
|
||||||
border-radius: 14px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-card span {
|
.metric-card span {
|
||||||
@@ -219,7 +219,7 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.up { color: #059669; }
|
.up { color: var(--success); }
|
||||||
.danger { color: #ef4444; }
|
.danger { color: #ef4444; }
|
||||||
|
|
||||||
.amount { left: 20px; top: 20px; }
|
.amount { left: 20px; top: 20px; }
|
||||||
@@ -252,7 +252,7 @@
|
|||||||
width: 220px;
|
width: 220px;
|
||||||
height: 214px;
|
height: 214px;
|
||||||
padding: 28px 28px;
|
padding: 28px 28px;
|
||||||
border-radius: 16px;
|
border-radius: 8px;
|
||||||
transform: rotate(2deg);
|
transform: rotate(2deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,10 +281,10 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: linear-gradient(135deg, #6ee7b7, #059669);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 27px;
|
font-size: 27px;
|
||||||
box-shadow: 0 14px 28px rgba(5,150,105,.25);
|
box-shadow: 0 14px 28px rgba(var(--theme-primary-rgb, 58, 124, 165), .22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shield-art {
|
.shield-art {
|
||||||
@@ -337,7 +337,7 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
border: 1px solid rgba(215, 224, 234, .82);
|
border: 1px solid rgba(215, 224, 234, .82);
|
||||||
border-radius: 13px;
|
border-radius: 6px;
|
||||||
background: rgba(255,255,255,.76);
|
background: rgba(255,255,255,.76);
|
||||||
box-shadow: 0 12px 30px rgba(65, 88, 110, .08);
|
box-shadow: 0 12px 30px rgba(65, 88, 110, .08);
|
||||||
backdrop-filter: blur(16px);
|
backdrop-filter: blur(16px);
|
||||||
@@ -352,7 +352,7 @@
|
|||||||
font-size: 21px;
|
font-size: 21px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-strip .green { background: #dff7ee; color: #059669; }
|
.feature-strip .primary { background: var(--theme-primary-soft); color: var(--theme-primary-active); }
|
||||||
.feature-strip .red { background: #fee2e2; color: #ef4444; }
|
.feature-strip .red { background: #fee2e2; color: #ef4444; }
|
||||||
.feature-strip .blue { background: #dbeafe; color: #3b82f6; }
|
.feature-strip .blue { background: #dbeafe; color: #3b82f6; }
|
||||||
|
|
||||||
@@ -379,7 +379,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
padding: 58px 60px 44px;
|
padding: 58px 60px 44px;
|
||||||
border: 1px solid rgba(215, 224, 234, .96);
|
border: 1px solid rgba(215, 224, 234, .96);
|
||||||
border-radius: 20px;
|
border-radius: 8px;
|
||||||
background: rgba(255,255,255,.86);
|
background: rgba(255,255,255,.86);
|
||||||
box-shadow: 0 24px 64px rgba(65, 88, 110, .16);
|
box-shadow: 0 24px 64px rgba(65, 88, 110, .16);
|
||||||
backdrop-filter: blur(18px);
|
backdrop-filter: blur(18px);
|
||||||
@@ -450,9 +450,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.field input:focus {
|
.field input:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 0 0 3px rgba(16,185,129,.13);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring, rgba(58, 124, 165, .14));
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +471,7 @@
|
|||||||
|
|
||||||
.field-icon-btn:hover {
|
.field-icon-btn:hover {
|
||||||
background: #f1f5f9;
|
background: #f1f5f9;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-meta {
|
.form-meta {
|
||||||
@@ -503,7 +503,7 @@
|
|||||||
.remember input {
|
.remember input {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
accent-color: #059669;
|
accent-color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-btn {
|
.link-btn {
|
||||||
@@ -529,13 +529,13 @@
|
|||||||
.submit-btn {
|
.submit-btn {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 16px 30px rgba(5,150,105,.20);
|
box-shadow: 0 16px 30px rgba(var(--theme-primary-rgb, 58, 124, 165), .20);
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit-btn:hover {
|
.submit-btn:hover {
|
||||||
background: linear-gradient(135deg, #13c990, #047857);
|
background: linear-gradient(135deg, var(--theme-primary-hover), var(--theme-primary-active));
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit-btn:disabled,
|
.submit-btn:disabled,
|
||||||
@@ -571,13 +571,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sso-btn {
|
.sso-btn {
|
||||||
border: 1px solid #10b981;
|
border: 1px solid var(--theme-primary);
|
||||||
background: rgba(255,255,255,.78);
|
background: rgba(255,255,255,.78);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sso-btn:hover {
|
.sso-btn:hover {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.security-note {
|
.security-note {
|
||||||
@@ -689,7 +689,7 @@
|
|||||||
|
|
||||||
.login-card {
|
.login-card {
|
||||||
padding: 32px 22px 24px;
|
padding: 32px 22px 24px;
|
||||||
border-radius: 14px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-head h2 {
|
.card-head h2 {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
.console-tabs button:hover,
|
.console-tabs button:hover,
|
||||||
.console-tabs button.active {
|
.console-tabs button.active {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.console-tabs button.active::after {
|
.console-tabs button.active::after {
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
bottom: -11px;
|
bottom: -11px;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.console-toolbar {
|
.console-toolbar {
|
||||||
@@ -102,7 +102,6 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-field select,
|
|
||||||
.field-input {
|
.field-input {
|
||||||
min-height: 38px;
|
min-height: 38px;
|
||||||
border: 1px solid #d8e1eb;
|
border: 1px solid #d8e1eb;
|
||||||
@@ -110,12 +109,6 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-field select {
|
|
||||||
padding: 0 12px;
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-input {
|
.field-input {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -148,7 +141,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-btn.primary {
|
.toolbar-btn.primary {
|
||||||
background: linear-gradient(135deg, #0f9f8d, #10b981);
|
background: var(--theme-gradient-primary);
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
@@ -247,12 +240,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.log-table tbody tr:hover {
|
.log-table tbody tr:hover {
|
||||||
background: rgba(16, 185, 129, 0.04);
|
background: rgba(var(--theme-primary-rgb), 0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-table tbody tr.active {
|
.log-table tbody tr.active {
|
||||||
background: rgba(16, 185, 129, 0.08);
|
background: rgba(var(--theme-primary-rgb), 0.08);
|
||||||
box-shadow: inset 3px 0 0 #10b981;
|
box-shadow: inset 3px 0 0 var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-table tbody td {
|
.log-table tbody td {
|
||||||
@@ -363,14 +356,14 @@
|
|||||||
|
|
||||||
.pager button:hover:not(.active):not(:disabled) {
|
.pager button:hover:not(.active):not(:disabled) {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pager button.active {
|
.pager button.active {
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 16px rgba(5, 150, 105, 0.2);
|
box-shadow: 0 8px 16px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-nav:disabled {
|
.page-nav:disabled {
|
||||||
@@ -378,63 +371,11 @@
|
|||||||
opacity: 0.45;
|
opacity: 0.45;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size-wrap {
|
.page-size-select {
|
||||||
position: relative;
|
width: 112px;
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size {
|
|
||||||
min-width: 112px;
|
|
||||||
min-height: 38px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 9px;
|
|
||||||
padding: 0 14px;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 750;
|
|
||||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
bottom: calc(100% + 6px);
|
|
||||||
z-index: 40;
|
|
||||||
display: grid;
|
|
||||||
overflow: hidden;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.14);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button {
|
|
||||||
height: 36px;
|
|
||||||
padding: 0 20px;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
background: transparent;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 750;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button:hover {
|
|
||||||
background: #f0fdf4;
|
|
||||||
color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button.active {
|
|
||||||
background: #059669;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.analytics-row {
|
.analytics-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) minmax(260px, 0.48fr);
|
grid-template-columns: minmax(0, 1fr) minmax(260px, 0.48fr);
|
||||||
@@ -473,8 +414,8 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 9px;
|
padding: 0 9px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-light-9);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@@ -540,7 +481,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.trend-line.total {
|
.trend-line.total {
|
||||||
stroke: #10b981;
|
stroke: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.trend-line.failed {
|
.trend-line.failed {
|
||||||
@@ -644,9 +585,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.success {
|
.status-pill.success {
|
||||||
background: rgba(22, 163, 74, 0.12);
|
background: rgba(var(--success-rgb), 0.12);
|
||||||
border-color: rgba(22, 163, 74, 0.2);
|
border-color: rgba(var(--success-rgb), 0.2);
|
||||||
color: #166534;
|
color: var(--success-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.warning {
|
.status-pill.warning {
|
||||||
@@ -761,8 +702,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pager,
|
.pager,
|
||||||
.page-size,
|
.page-size-select {
|
||||||
.page-size-wrap {
|
|
||||||
justify-self: stretch;
|
justify-self: stretch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,8 +98,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.kpi-badge.down {
|
.kpi-badge.down {
|
||||||
background: rgba(22, 163, 74, 0.08);
|
background: rgba(var(--success-rgb), 0.08);
|
||||||
color: #16a34a;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.kpi-badge .mdi {
|
.kpi-badge .mdi {
|
||||||
@@ -157,9 +157,13 @@
|
|||||||
|
|
||||||
.card-head h3 {
|
.card-head h3 {
|
||||||
color: #1e293b;
|
color: #1e293b;
|
||||||
font-size: 16px;
|
font-size: 15px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-head .mdi {
|
.card-head .mdi {
|
||||||
@@ -169,14 +173,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card-select {
|
.card-select {
|
||||||
height: 30px;
|
width: 110px;
|
||||||
min-width: 82px;
|
|
||||||
padding: 0 8px;
|
|
||||||
border: 1px solid #cbd5e1;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: #fff;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-note {
|
.panel-note {
|
||||||
@@ -226,8 +223,8 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #e2f6ef;
|
background: var(--theme-primary-light-9);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@@ -272,8 +269,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-tag.success {
|
.status-tag.success {
|
||||||
background: rgba(16,185,129,.10);
|
background: rgba(var(--success-rgb), .10);
|
||||||
color: #16a34a;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-link {
|
.text-link {
|
||||||
@@ -286,7 +283,7 @@
|
|||||||
border: 0;
|
border: 0;
|
||||||
border-top: 1px solid #f1f5f9;
|
border-top: 1px solid #f1f5f9;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,8 +131,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.folder-tree button.active {
|
.folder-tree button.active {
|
||||||
background: #dcfce7;
|
background: var(--theme-primary-light-9);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,10 +159,10 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
border: 1px solid rgba(16, 185, 129, .28);
|
border: 1px solid rgba(var(--theme-primary-rgb), .28);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #f0fdf4;
|
background: var(--theme-primary-light-9);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
@@ -178,9 +178,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.knowledge-sync-btn:not(:disabled):hover {
|
.knowledge-sync-btn:not(:disabled):hover {
|
||||||
border-color: rgba(16, 185, 129, 0.38);
|
border-color: rgba(var(--theme-primary-rgb), 0.38);
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-light-9);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-sync-meta {
|
.folder-sync-meta {
|
||||||
@@ -299,8 +299,8 @@ th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.doc-row.selected {
|
.doc-row.selected {
|
||||||
background: linear-gradient(90deg, rgba(16, 185, 129, 0.08), rgba(59, 130, 246, 0.04));
|
background: linear-gradient(90deg, rgba(var(--theme-primary-rgb), 0.08), rgba(59, 130, 246, 0.04));
|
||||||
box-shadow: inset 3px 0 0 #10b981;
|
box-shadow: inset 3px 0 0 var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-name {
|
.file-name {
|
||||||
@@ -316,7 +316,7 @@ th {
|
|||||||
.file-name .word,
|
.file-name .word,
|
||||||
.viewer-filetype.word { color: #2563eb; }
|
.viewer-filetype.word { color: #2563eb; }
|
||||||
.file-name .excel,
|
.file-name .excel,
|
||||||
.viewer-filetype.excel { color: #10b981; }
|
.viewer-filetype.excel { color: var(--success); }
|
||||||
|
|
||||||
.doc-tag {
|
.doc-tag {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -342,8 +342,8 @@ th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.state-tag.success {
|
.state-tag.success {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-tag.muted {
|
.state-tag.muted {
|
||||||
@@ -394,7 +394,7 @@ th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.more-btn.ingest {
|
.more-btn.ingest {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.more-btn.llm-wiki-view {
|
.more-btn.llm-wiki-view {
|
||||||
@@ -464,14 +464,14 @@ th {
|
|||||||
|
|
||||||
.pager button:hover:not(.active) {
|
.pager button:hover:not(.active) {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pager button.active {
|
.pager button.active {
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 16px rgba(5, 150, 105, .20);
|
box-shadow: 0 8px 16px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-foot .page-summary {
|
.list-foot .page-summary {
|
||||||
@@ -484,74 +484,11 @@ th {
|
|||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size-wrap {
|
.page-size-select {
|
||||||
position: relative;
|
width: 112px;
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size {
|
|
||||||
justify-self: end;
|
|
||||||
min-width: 112px;
|
|
||||||
min-height: 38px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 9px;
|
|
||||||
padding: 0 14px;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
|
|
||||||
color: #334155;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 750;
|
|
||||||
white-space: nowrap;
|
|
||||||
transition: border-color 160ms ease, color 160ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size:hover {
|
|
||||||
border-color: rgba(16, 185, 129, .32);
|
|
||||||
color: #0f9f78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown {
|
|
||||||
position: absolute;
|
|
||||||
bottom: calc(100% + 6px);
|
|
||||||
right: 0;
|
|
||||||
z-index: 40;
|
|
||||||
display: grid;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 12px 32px rgba(15, 23, 42, .14);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button {
|
|
||||||
height: 36px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
background: transparent;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 750;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 0 20px;
|
|
||||||
transition: background 120ms ease, color 120ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button:hover {
|
|
||||||
background: #f0fdf4;
|
|
||||||
color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button.active {
|
|
||||||
background: #059669;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-panel {
|
.preview-panel {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -671,7 +608,7 @@ th {
|
|||||||
|
|
||||||
.llm-wiki-overlay {
|
.llm-wiki-overlay {
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top, rgba(15, 118, 110, 0.12), transparent 30%),
|
radial-gradient(circle at top, rgba(var(--theme-primary-rgb), 0.12), transparent 30%),
|
||||||
rgba(15, 23, 42, 0.58);
|
rgba(15, 23, 42, 0.58);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,8 +643,8 @@ th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.llm-wiki-count {
|
.llm-wiki-count {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-light-9);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.llm-wiki-stat-grid {
|
.llm-wiki-stat-grid {
|
||||||
@@ -838,8 +775,8 @@ th {
|
|||||||
|
|
||||||
.llm-wiki-editor:focus {
|
.llm-wiki-editor:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: rgba(16, 185, 129, 0.42);
|
border-color: rgba(var(--theme-primary-rgb), 0.42);
|
||||||
box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.12);
|
box-shadow: 0 0 0 4px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.llm-wiki-candidate-list {
|
.llm-wiki-candidate-list {
|
||||||
@@ -1253,8 +1190,7 @@ th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pager,
|
.pager,
|
||||||
.page-size-wrap,
|
.page-size-select {
|
||||||
.page-size {
|
|
||||||
justify-self: stretch;
|
justify-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,8 +47,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.list-search input:focus {
|
.list-search input:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.14);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active {
|
.status-tabs button.active {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active::after {
|
.status-tabs button.active::after {
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
bottom: -1px;
|
bottom: -1px;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
border-radius: 999px 999px 0 0;
|
border-radius: 999px 999px 0 0;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-toolbar {
|
.list-toolbar {
|
||||||
@@ -108,23 +108,22 @@
|
|||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: var(--theme-gradient-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
box-shadow: 0 10px 24px rgba(5, 150, 105, 0.2);
|
box-shadow: 0 10px 24px var(--theme-primary-shadow);
|
||||||
transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
|
transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-request-btn:hover {
|
.create-request-btn:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 0 14px 28px rgba(5, 150, 105, 0.24);
|
box-shadow: 0 14px 28px rgba(var(--theme-primary-rgb), 0.24);
|
||||||
filter: saturate(1.02);
|
filter: saturate(1.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-btn,
|
.filter-btn {
|
||||||
.page-size {
|
|
||||||
min-height: 38px;
|
min-height: 38px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -232,8 +231,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.date-range-fields input:focus {
|
.date-range-fields input:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, .12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +253,7 @@
|
|||||||
|
|
||||||
.apply-btn {
|
.apply-btn {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,10 +262,9 @@
|
|||||||
background: #cbd5e1;
|
background: #cbd5e1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-btn:hover,
|
.filter-btn:hover {
|
||||||
.page-size:hover {
|
border-color: rgba(var(--theme-primary-rgb), .32);
|
||||||
border-color: rgba(16, 185, 129, .32);
|
color: var(--theme-primary-active);
|
||||||
color: #0f9f78;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
@@ -289,7 +287,7 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border: 1px solid #edf2f7;
|
border: 1px solid #edf2f7;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: linear-gradient(180deg, #fcfefd 0%, #f4f8f6 100%);
|
background: linear-gradient(180deg, #fcfefd 0%, var(--theme-primary-light-9) 100%);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
@@ -316,13 +314,13 @@
|
|||||||
padding: 28px 20px;
|
padding: 28px 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
background: linear-gradient(180deg, #fcfffd 0%, #f5f9f7 100%);
|
background: linear-gradient(180deg, #fcfffd 0%, var(--theme-primary-light-9) 100%);
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-state .mdi {
|
.table-state .mdi {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-state strong {
|
.table-state strong {
|
||||||
@@ -399,7 +397,7 @@ tbody tr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tbody tr:hover {
|
tbody tr:hover {
|
||||||
background: linear-gradient(90deg, rgba(16, 185, 129, .08), rgba(16, 185, 129, .03));
|
background: linear-gradient(90deg, rgba(var(--theme-primary-rgb), .08), rgba(var(--theme-primary-rgb), .03));
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody tr:last-child td {
|
tbody tr:last-child td {
|
||||||
@@ -407,7 +405,7 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.doc-id {
|
.doc-id {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,8 +422,8 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.type-tag.travel {
|
.type-tag.travel {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-light-9);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.type-tag.entertainment {
|
.type-tag.entertainment {
|
||||||
@@ -435,8 +433,8 @@ tbody tr:last-child td {
|
|||||||
|
|
||||||
.type-tag.hotel,
|
.type-tag.hotel,
|
||||||
.type-tag.transport {
|
.type-tag.transport {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-light-9);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.type-tag.meal {
|
.type-tag.meal {
|
||||||
@@ -479,9 +477,9 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-tag.success {
|
.status-tag.success {
|
||||||
border-color: #bbf7d0;
|
border-color: var(--success-line);
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tag.warning {
|
.status-tag.warning {
|
||||||
@@ -546,69 +544,23 @@ tbody tr:last-child td {
|
|||||||
|
|
||||||
.pager button:hover:not(.active) {
|
.pager button:hover:not(.active) {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
box-shadow: 0 1px 4px rgba(15, 23, 42, .08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pager button.active {
|
.pager button.active {
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 16px rgba(5, 150, 105, .20);
|
box-shadow: 0 8px 16px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-nav {
|
.page-nav {
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-size {
|
.page-size-select {
|
||||||
|
width: 112px;
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
min-width: 112px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-wrap {
|
|
||||||
position: relative;
|
|
||||||
justify-self: end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown {
|
|
||||||
position: absolute;
|
|
||||||
bottom: calc(100% + 6px);
|
|
||||||
right: 0;
|
|
||||||
z-index: 40;
|
|
||||||
display: grid;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 12px 32px rgba(15, 23, 42, .14);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button {
|
|
||||||
height: 36px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
background: transparent;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 750;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 0 20px;
|
|
||||||
transition: background 120ms ease, color 120ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button:hover {
|
|
||||||
background: #f0fdf4;
|
|
||||||
color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-size-dropdown button.active {
|
|
||||||
background: #059669;
|
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
@@ -629,7 +581,7 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter-btn,
|
.filter-btn,
|
||||||
.page-size {
|
.page-size-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,7 +595,7 @@ tbody tr:last-child td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pager,
|
.pager,
|
||||||
.page-size {
|
.page-size-select {
|
||||||
justify-self: stretch;
|
justify-self: stretch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* 设置页表单/卡片/开关 — 供 SettingsView 与子面板各自 scoped 引入 */
|
/* 设置页表单、卡片与开关样式,供 SettingsView 及子面板 scoped 引入 */
|
||||||
|
|
||||||
.settings-card {
|
.settings-card {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 12px;
|
border-radius: 6px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02), 0 4px 16px rgba(0, 0, 0, 0.03);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02), 0 4px 16px rgba(0, 0, 0, 0.03);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -99,13 +99,12 @@
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field input,
|
.field input {
|
||||||
.field select {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 44px;
|
min-height: 44px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 1px solid #cbd5e1;
|
border: 1px solid #cbd5e1;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -117,11 +116,10 @@
|
|||||||
color: #94a3b8;
|
color: #94a3b8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field input:focus,
|
.field input:focus {
|
||||||
.field select:focus {
|
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.08);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +136,7 @@
|
|||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 16px;
|
border-radius: 6px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
transition: all 0.25s ease;
|
transition: all 0.25s ease;
|
||||||
@@ -147,9 +145,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.switch-row:hover {
|
.switch-row:hover {
|
||||||
border-color: rgba(16, 185, 129, 0.25);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.25);
|
||||||
background: linear-gradient(180deg, #ffffff 0%, rgba(16, 185, 129, 0.01) 100%);
|
background: linear-gradient(180deg, #ffffff 0%, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.02) 100%);
|
||||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.03);
|
box-shadow: 0 4px 12px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.04);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +196,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.switch-btn.active {
|
.switch-btn.active {
|
||||||
background-color: #10b981;
|
background-color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.switch-btn.active i {
|
.switch-btn.active i {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
/* Master Control Hero Card Active Hover & Color */
|
/* Master Control Hero Card Active Hover & Color */
|
||||||
.hermes-hero-card.active {
|
.hermes-hero-card.active {
|
||||||
border-color: rgba(16, 185, 129, 0.25);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.25);
|
||||||
background: linear-gradient(180deg, #ffffff 0%, rgba(16, 185, 129, 0.02) 100%);
|
background: linear-gradient(180deg, #ffffff 0%, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.02) 100%);
|
||||||
box-shadow: 0 1px 3px rgba(16, 185, 129, 0.01), 0 8px 24px rgba(16, 185, 129, 0.05);
|
box-shadow: 0 1px 3px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.01), 0 8px 24px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hermes-hero-card .model-icon-box {
|
.hermes-hero-card .model-icon-box {
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hermes-hero-card .model-icon-box.active {
|
.hermes-hero-card .model-icon-box.active {
|
||||||
background: rgba(16, 185, 129, 0.1);
|
background: var(--theme-primary-soft);
|
||||||
color: #10b981;
|
color: var(--theme-primary-active);
|
||||||
border-color: rgba(16, 185, 129, 0.15);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pulse Dot */
|
/* Pulse Dot */
|
||||||
@@ -37,19 +37,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-pulse-dot.active {
|
.status-pulse-dot.active {
|
||||||
background-color: #10b981;
|
background-color: var(--theme-primary);
|
||||||
animation: pulse-ring 1.8s cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite;
|
animation: pulse-ring 1.8s cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse-ring {
|
@keyframes pulse-ring {
|
||||||
0% {
|
0% {
|
||||||
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4);
|
box-shadow: 0 0 0 0 rgba(var(--theme-primary-rgb, 58, 124, 165), 0.36);
|
||||||
}
|
}
|
||||||
70% {
|
70% {
|
||||||
box-shadow: 0 0 0 6px rgba(16, 185, 129, 0);
|
box-shadow: 0 0 0 6px rgba(var(--theme-primary-rgb, 58, 124, 165), 0);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
|
box-shadow: 0 0 0 0 rgba(var(--theme-primary-rgb, 58, 124, 165), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,8 +65,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-badge.active {
|
.status-badge.active {
|
||||||
background: rgba(16, 185, 129, 0.1);
|
background: var(--theme-primary-soft);
|
||||||
color: #10b981;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Task Section */
|
/* Task Section */
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 16px;
|
border-radius: 6px;
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.01), 0 2px 8px rgba(0, 0, 0, 0.02);
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.01), 0 2px 8px rgba(0, 0, 0, 0.02);
|
||||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
border-radius: 12px;
|
border-radius: 6px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
@@ -185,13 +185,13 @@
|
|||||||
|
|
||||||
.frequency-badge.active {
|
.frequency-badge.active {
|
||||||
background: #f0f9ff;
|
background: #f0f9ff;
|
||||||
color: #0284c7;
|
color: #2f6d95;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-picker-wrapper input[type="time"] {
|
.time-picker-wrapper input[type="time"] {
|
||||||
padding: 5px 8px;
|
padding: 5px 8px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #f8fafc;
|
background: #f8fafc;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -207,9 +207,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.time-picker-wrapper input[type="time"]:focus {
|
.time-picker-wrapper input[type="time"]:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.08);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-picker-placeholder {
|
.time-picker-placeholder {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 240px minmax(0, 1fr);
|
grid-template-columns: 240px minmax(0, 1fr);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 24px;
|
border-radius: 4px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #e2e8f0;
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02), 0 4px 16px rgba(0, 0, 0, 0.03);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02), 0 4px 16px rgba(0, 0, 0, 0.03);
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-kicker {
|
.nav-kicker {
|
||||||
color: #10b981;
|
color: var(--primary);
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -84,9 +84,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.settings-nav-item.active {
|
.settings-nav-item.active {
|
||||||
background: #ecfdf5;
|
background: var(--primary-soft);
|
||||||
color: #059669;
|
color: var(--primary-active);
|
||||||
border-color: rgba(16, 185, 129, 0.12);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-item-copy {
|
.nav-item-copy {
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.settings-nav-item.active .nav-item-copy small {
|
.settings-nav-item.active .nav-item-copy small {
|
||||||
color: #059669;
|
color: var(--primary-active);
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,9 +144,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 24px;
|
min-height: 24px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border-radius: 99px;
|
border-radius: 4px;
|
||||||
background: #ecfdf5;
|
background: var(--primary-soft);
|
||||||
color: #059669;
|
color: var(--primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@@ -181,20 +181,20 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
background: #10b981;
|
background: var(--primary);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.15);
|
box-shadow: 0 4px 12px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.16);
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.save-button:hover {
|
.save-button:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 0 6px 20px rgba(16, 185, 129, 0.25);
|
box-shadow: 0 6px 20px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.22);
|
||||||
background: #059669;
|
background: var(--primary-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-content {
|
.settings-content {
|
||||||
@@ -219,10 +219,10 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.2);
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.22);
|
||||||
border-radius: 10px;
|
border-radius: 4px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12.5px;
|
font-size: 12.5px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
@@ -231,10 +231,10 @@
|
|||||||
|
|
||||||
.test-button:hover:not(:disabled) {
|
.test-button:hover:not(:disabled) {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.15);
|
box-shadow: 0 4px 12px rgba(58, 124, 165, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-button:disabled {
|
.test-button:disabled {
|
||||||
@@ -259,7 +259,7 @@
|
|||||||
gap: 10px;
|
gap: 10px;
|
||||||
padding: 0 40px 0 14px;
|
padding: 0 40px 0 14px;
|
||||||
border: 1px solid #cbd5e1;
|
border: 1px solid #cbd5e1;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -287,18 +287,18 @@
|
|||||||
|
|
||||||
.session-picker-trigger:hover,
|
.session-picker-trigger:hover,
|
||||||
.session-picker-filter.open .session-picker-trigger {
|
.session-picker-filter.open .session-picker-trigger {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.session-picker-filter.open .session-picker-trigger {
|
.session-picker-filter.open .session-picker-trigger {
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.08);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.session-picker-filter.open .session-picker-trigger .mdi,
|
.session-picker-filter.open .session-picker-trigger .mdi,
|
||||||
.session-picker-trigger:hover .mdi {
|
.session-picker-trigger:hover .mdi {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.session-picker-popover {
|
.session-picker-popover {
|
||||||
@@ -311,7 +311,7 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border: 1px solid #cbd5e1;
|
border: 1px solid #cbd5e1;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.05), 0 8px 10px -6px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.05), 0 8px 10px -6px rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
@@ -335,7 +335,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -360,7 +360,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border: 1px solid #cbd5e1;
|
border: 1px solid #cbd5e1;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -372,9 +372,123 @@
|
|||||||
|
|
||||||
.session-picker-option:hover,
|
.session-picker-option:hover,
|
||||||
.session-picker-option.active {
|
.session-picker-option.active {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-option-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-option {
|
||||||
|
min-height: 104px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
padding: 16px;
|
||||||
|
border: 1px solid #d8dee8;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #334155;
|
||||||
|
text-align: left;
|
||||||
|
transition:
|
||||||
|
border-color 160ms var(--ease),
|
||||||
|
background 160ms var(--ease),
|
||||||
|
box-shadow 160ms var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-option:hover,
|
||||||
|
.skin-option.active {
|
||||||
|
border-color: var(--primary);
|
||||||
|
background: var(--theme-primary-light-9);
|
||||||
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-swatch {
|
||||||
|
width: 64px;
|
||||||
|
height: 38px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.3fr 1fr 1fr 1fr;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
border: 1px solid #d8dee8;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-swatch i + i {
|
||||||
|
border-left: 1px solid rgba(255, 255, 255, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-copy {
|
||||||
|
display: grid;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-copy strong {
|
||||||
|
color: #111827;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-copy small {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-current {
|
||||||
|
min-height: 24px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.26);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--primary-soft);
|
||||||
|
color: var(--primary-active);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-preview-panel {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
border: 1px solid #d8dee8;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: linear-gradient(180deg, #ffffff 0%, var(--theme-primary-light-9) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-preview-panel div {
|
||||||
|
display: grid;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-preview-panel strong {
|
||||||
|
color: #111827;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-preview-panel span {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-preview-action {
|
||||||
|
min-height: 34px;
|
||||||
|
padding: 0 14px;
|
||||||
|
border: 1px solid var(--primary);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--theme-gradient-primary);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.secret-bound-state {
|
.secret-bound-state {
|
||||||
@@ -382,7 +496,7 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.45;
|
line-height: 1.45;
|
||||||
@@ -398,7 +512,7 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
border-radius: 12px;
|
border-radius: 6px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
@@ -410,13 +524,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.test-feedback.is-success {
|
.test-feedback.is-success {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-feedback.is-error {
|
.test-feedback.is-error {
|
||||||
background: #fef2f2;
|
background: var(--danger-soft);
|
||||||
color: #b91c1c;
|
color: var(--danger-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-feedback.is-testing {
|
.test-feedback.is-testing {
|
||||||
@@ -434,13 +548,13 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 1px dashed #cbd5e1;
|
border: 1px dashed #cbd5e1;
|
||||||
border-radius: 20px;
|
border-radius: 8px;
|
||||||
background:
|
background:
|
||||||
linear-gradient(45deg, #f8fafc 25%, transparent 25%, transparent 75%, #f8fafc 75%, #f8fafc),
|
linear-gradient(45deg, #f8fafc 25%, transparent 25%, transparent 75%, #f8fafc 75%, #f8fafc),
|
||||||
linear-gradient(45deg, #f8fafc 25%, transparent 25%, transparent 75%, #f8fafc 75%, #f8fafc);
|
linear-gradient(45deg, #f8fafc 25%, transparent 25%, transparent 75%, #f8fafc 75%, #f8fafc);
|
||||||
background-position: 0 0, 9px 9px;
|
background-position: 0 0, 9px 9px;
|
||||||
background-size: 18px 18px;
|
background-size: 18px 18px;
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,9 +564,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 18px;
|
gap: 18px;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.15);
|
border: 1px solid rgba(58, 124, 165, 0.15);
|
||||||
border-radius: 20px;
|
border-radius: 8px;
|
||||||
background: linear-gradient(135deg, rgba(16, 185, 129, 0.04) 0%, rgba(59, 130, 246, 0.02) 100%);
|
background: linear-gradient(135deg, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.06) 0%, rgba(var(--theme-secondary-rgb, 37, 99, 235), 0.03) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-icon {
|
.preview-icon {
|
||||||
@@ -460,11 +574,11 @@
|
|||||||
height: 64px;
|
height: 64px;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 16px;
|
border-radius: 8px;
|
||||||
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
background: var(--theme-gradient-primary);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
box-shadow: 0 8px 20px rgba(16, 185, 129, 0.15);
|
box-shadow: 0 8px 20px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-copy strong {
|
.preview-copy strong {
|
||||||
@@ -495,9 +609,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border-radius: 999px;
|
border-radius: 4px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -515,7 +629,7 @@
|
|||||||
min-height: 34px;
|
min-height: 34px;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
border: 1px solid #cbd5e1;
|
border: 1px solid #cbd5e1;
|
||||||
border-radius: 999px;
|
border-radius: 4px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -525,16 +639,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.level-chip:hover {
|
.level-chip:hover {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-chip.active {
|
.level-chip.active {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.2);
|
box-shadow: 0 4px 12px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.range-shell {
|
.range-shell {
|
||||||
@@ -544,13 +658,13 @@
|
|||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 1px solid #cbd5e1;
|
border: 1px solid #cbd5e1;
|
||||||
border-radius: 12px;
|
border-radius: 4px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.range-shell input[type='range'] {
|
.range-shell input[type='range'] {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
accent-color: #10b981;
|
accent-color: var(--theme-primary);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,7 +680,7 @@
|
|||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 大语言模型配置卡片特定图标与标题排版 */
|
/* 大语言模型配置卡片图标与标题排版 */
|
||||||
.card-title-with-icon {
|
.card-title-with-icon {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -578,7 +692,7 @@
|
|||||||
height: 40px;
|
height: 40px;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 10px;
|
border-radius: 6px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
background: #f8fafc;
|
background: #f8fafc;
|
||||||
@@ -681,7 +795,7 @@
|
|||||||
|
|
||||||
.settings-card {
|
.settings-card {
|
||||||
padding: 20px 16px;
|
padding: 20px 16px;
|
||||||
border-radius: 16px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-nav {
|
.settings-nav {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(320px, 392px) minmax(0, 1fr);
|
grid-template-columns: minmax(320px, 392px) minmax(0, 1fr);
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top left, rgba(16, 185, 129, 0.24), transparent 24rem),
|
radial-gradient(circle at top left, rgba(var(--theme-primary-rgb), 0.24), transparent 24rem),
|
||||||
radial-gradient(circle at 36% 14%, rgba(16, 185, 129, 0.16), transparent 18rem),
|
radial-gradient(circle at 36% 14%, rgba(var(--theme-primary-rgb), 0.16), transparent 18rem),
|
||||||
linear-gradient(135deg, #04110d 0%, #0b1f18 26%, #10281f 26%, #eef5f1 26%, #f6fbf8 100%);
|
linear-gradient(135deg, #04110d 0%, #0b1f18 26%, #10281f 26%, #eef5f1 26%, #f6fbf8 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,10 +38,10 @@
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
background:
|
background:
|
||||||
linear-gradient(145deg, rgba(209, 250, 229, 0.96), rgba(52, 211, 153, 0.88)),
|
linear-gradient(145deg, color-mix(in srgb, var(--theme-primary-soft) 96%, white), rgba(var(--theme-primary-rgb), 0.58)),
|
||||||
linear-gradient(145deg, rgba(16, 185, 129, 0.4), rgba(5, 150, 105, 0.6));
|
linear-gradient(145deg, rgba(var(--theme-primary-rgb), 0.4), rgba(var(--theme-primary-rgb), 0.6));
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 18px 36px rgba(16, 185, 129, 0.2),
|
0 18px 36px rgba(var(--theme-primary-rgb), 0.2),
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.46);
|
inset 0 1px 0 rgba(255, 255, 255, 0.46);
|
||||||
transform: rotate(-8deg);
|
transform: rotate(-8deg);
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 7px;
|
inset: 7px;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
border: 1px solid rgba(4, 120, 87, 0.22);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-brand-core {
|
.setup-brand-core {
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: rgba(3, 32, 24, 0.92);
|
background: rgba(3, 32, 24, 0.92);
|
||||||
color: #d1fae5;
|
color: var(--theme-primary-soft-strong);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 0.14em;
|
letter-spacing: 0.14em;
|
||||||
@@ -77,22 +77,22 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.12em;
|
letter-spacing: 0.12em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: rgba(167, 243, 208, 0.86);
|
color: color-mix(in srgb, var(--theme-primary-soft) 86%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-kicker-light {
|
.setup-kicker-light {
|
||||||
color: rgba(209, 250, 229, 0.82);
|
color: color-mix(in srgb, var(--theme-primary-soft) 82%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-context h1 {
|
.setup-context h1 {
|
||||||
color: #f4fff8;
|
color: #f8fafc;
|
||||||
font-size: clamp(1.9rem, 2.4vw, 2.5rem);
|
font-size: clamp(1.9rem, 2.4vw, 2.5rem);
|
||||||
line-height: 1.08;
|
line-height: 1.08;
|
||||||
text-shadow: 0 12px 36px rgba(2, 12, 8, 0.34);
|
text-shadow: 0 12px 36px rgba(2, 12, 8, 0.34);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-lead {
|
.setup-lead {
|
||||||
color: rgba(220, 252, 231, 0.84);
|
color: rgba(226, 232, 240, 0.84);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.8;
|
line-height: 1.8;
|
||||||
}
|
}
|
||||||
@@ -105,13 +105,13 @@
|
|||||||
.setup-nav-item {
|
.setup-nav-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 14px 14px 14px 12px;
|
padding: 14px 14px 14px 12px;
|
||||||
border: 1px solid rgba(110, 231, 183, 0.12);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.14);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 44px minmax(0, 1fr) 18px;
|
grid-template-columns: 44px minmax(0, 1fr) 18px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
background: linear-gradient(160deg, rgba(10, 23, 18, 0.82), rgba(15, 39, 31, 0.72));
|
background: linear-gradient(160deg, rgba(10, 18, 27, 0.82), rgba(16, 31, 43, 0.72));
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
|
transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
|
||||||
@@ -119,16 +119,16 @@
|
|||||||
|
|
||||||
.setup-nav-item:hover {
|
.setup-nav-item:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
border-color: rgba(110, 231, 183, 0.22);
|
border-color: rgba(var(--theme-primary-rgb), 0.28);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-nav-item.is-active {
|
.setup-nav-item.is-active {
|
||||||
border-color: rgba(16, 185, 129, 0.4);
|
border-color: rgba(var(--theme-primary-rgb), 0.4);
|
||||||
box-shadow: 0 14px 28px rgba(3, 10, 7, 0.22);
|
box-shadow: 0 14px 28px rgba(3, 10, 7, 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-nav-item.is-complete {
|
.setup-nav-item.is-complete {
|
||||||
background: linear-gradient(160deg, rgba(8, 31, 23, 0.96), rgba(12, 58, 44, 0.86));
|
background: linear-gradient(160deg, rgba(10, 25, 36, 0.96), rgba(20, 50, 68, 0.86));
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-nav-index {
|
.setup-nav-index {
|
||||||
@@ -138,8 +138,8 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: rgba(16, 185, 129, 0.16);
|
background: rgba(var(--theme-primary-rgb), 0.16);
|
||||||
color: #d1fae5;
|
color: var(--theme-primary-soft-strong);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
@@ -151,12 +151,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setup-nav-copy strong {
|
.setup-nav-copy strong {
|
||||||
color: #f0fdf4;
|
color: var(--theme-primary-soft);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-nav-copy small {
|
.setup-nav-copy small {
|
||||||
color: rgba(209, 250, 229, 0.72);
|
color: color-mix(in srgb, var(--theme-primary-soft) 72%, transparent);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.55;
|
line-height: 1.55;
|
||||||
}
|
}
|
||||||
@@ -175,13 +175,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setup-progress strong {
|
.setup-progress strong {
|
||||||
color: #f0fdf4;
|
color: var(--theme-primary-soft);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-progress p {
|
.setup-progress p {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
color: rgba(209, 250, 229, 0.72);
|
color: color-mix(in srgb, var(--theme-primary-soft) 72%, transparent);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.65;
|
line-height: 1.65;
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setup-complete p {
|
.setup-complete p {
|
||||||
color: rgba(209, 250, 229, 0.76);
|
color: color-mix(in srgb, var(--theme-primary-soft) 76%, transparent);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
color: rgba(209, 250, 229, 0.86);
|
color: color-mix(in srgb, var(--theme-primary-soft) 86%, transparent);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@
|
|||||||
align-content: start;
|
align-content: start;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top left, rgba(16, 185, 129, 0.08), transparent 16rem),
|
radial-gradient(circle at top left, rgba(var(--theme-primary-rgb), 0.08), transparent 16rem),
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0));
|
linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 20px 22px;
|
padding: 20px 22px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.14);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.14);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: linear-gradient(135deg, #063b2e, #0f5f49);
|
background: linear-gradient(135deg, #063b2e, #0f5f49);
|
||||||
box-shadow: 0 16px 34px rgba(6, 59, 46, 0.16);
|
box-shadow: 0 16px 34px rgba(6, 59, 46, 0.16);
|
||||||
@@ -253,20 +253,20 @@
|
|||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(240, 253, 244, 0.14);
|
background: rgba(255, 255, 255, 0.12);
|
||||||
color: #d1fae5;
|
color: var(--theme-primary-soft-strong);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
border: 1px solid rgba(209, 250, 229, 0.18);
|
border: 1px solid color-mix(in srgb, var(--theme-primary-soft) 18%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-chip.is-success {
|
.setup-chip.is-success {
|
||||||
background: rgba(16, 185, 129, 0.22);
|
background: rgba(var(--theme-primary-rgb), 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-form {
|
.setup-form {
|
||||||
padding: 30px 32px;
|
padding: 30px 32px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.18);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.18);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: linear-gradient(180deg, rgba(244, 255, 248, 0.98), rgba(255, 255, 255, 0.94));
|
background: linear-gradient(180deg, rgba(244, 255, 248, 0.98), rgba(255, 255, 255, 0.94));
|
||||||
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
|
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
|
||||||
@@ -329,7 +329,7 @@
|
|||||||
|
|
||||||
.optional-block {
|
.optional-block {
|
||||||
padding: 18px 18px 0;
|
padding: 18px 18px 0;
|
||||||
border: 1px dashed rgba(16, 185, 129, 0.22);
|
border: 1px dashed rgba(var(--theme-primary-rgb), 0.22);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: rgba(240, 253, 244, 0.52);
|
background: rgba(240, 253, 244, 0.52);
|
||||||
}
|
}
|
||||||
@@ -353,8 +353,8 @@
|
|||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: rgba(16, 185, 129, 0.12);
|
background: rgba(var(--theme-primary-rgb), 0.12);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@@ -375,8 +375,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.field input:focus {
|
.field input:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.12);
|
box-shadow: 0 0 0 4px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-span-2 {
|
.field-span-2 {
|
||||||
@@ -406,7 +406,7 @@
|
|||||||
inset: 0 auto auto 0;
|
inset: 0 auto auto 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
background: linear-gradient(90deg, rgba(209, 250, 229, 0.92), rgba(16, 185, 129, 0.48));
|
background: linear-gradient(90deg, color-mix(in srgb, var(--theme-primary-soft) 92%, transparent), rgba(var(--theme-primary-rgb), 0.48));
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-runtime article:nth-child(1) {
|
.setup-runtime article:nth-child(1) {
|
||||||
@@ -453,9 +453,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setup-status.is-success {
|
.setup-status.is-success {
|
||||||
border: 1px solid rgba(16, 185, 129, 0.18);
|
border: 1px solid rgba(var(--theme-primary-rgb), 0.18);
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-status.is-danger {
|
.setup-status.is-danger {
|
||||||
@@ -502,19 +502,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.primary-btn {
|
.primary-btn {
|
||||||
background: linear-gradient(135deg, #10b981, #0f766e);
|
background: var(--theme-gradient-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 14px 28px rgba(16, 185, 129, 0.24);
|
box-shadow: 0 14px 28px rgba(var(--theme-primary-rgb), 0.24);
|
||||||
}
|
}
|
||||||
|
|
||||||
.secondary-btn {
|
.secondary-btn {
|
||||||
background: rgba(240, 253, 244, 0.94);
|
background: rgba(240, 253, 244, 0.94);
|
||||||
color: #1f4f41;
|
color: #1f4f41;
|
||||||
border-color: rgba(16, 185, 129, 0.18);
|
border-color: rgba(var(--theme-primary-rgb), 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
.secondary-btn-strong {
|
.secondary-btn-strong {
|
||||||
background: linear-gradient(135deg, rgba(16, 185, 129, 0.14), rgba(5, 150, 105, 0.12));
|
background: linear-gradient(135deg, rgba(var(--theme-primary-rgb), 0.14), rgba(var(--theme-primary-rgb), 0.12));
|
||||||
color: #065f46;
|
color: #065f46;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,7 +553,7 @@
|
|||||||
grid-template-rows: auto minmax(0, 1fr);
|
grid-template-rows: auto minmax(0, 1fr);
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top right, rgba(16, 185, 129, 0.16), transparent 18rem),
|
radial-gradient(circle at top right, rgba(var(--theme-primary-rgb), 0.16), transparent 18rem),
|
||||||
linear-gradient(180deg, #05251d 0%, #081611 100%);
|
linear-gradient(180deg, #05251d 0%, #081611 100%);
|
||||||
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.42);
|
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.42);
|
||||||
}
|
}
|
||||||
@@ -574,7 +574,7 @@
|
|||||||
.setup-startup-head span {
|
.setup-startup-head span {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
color: rgba(209, 250, 229, 0.78);
|
color: color-mix(in srgb, var(--theme-primary-soft) 78%, transparent);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
@@ -628,7 +628,7 @@
|
|||||||
|
|
||||||
.setup-startup-step .pi {
|
.setup-startup-step .pi {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
color: rgba(209, 250, 229, 0.46);
|
color: color-mix(in srgb, var(--theme-primary-soft) 46%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-startup-step strong {
|
.setup-startup-step strong {
|
||||||
@@ -639,7 +639,7 @@
|
|||||||
.setup-startup-step span {
|
.setup-startup-step span {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
color: rgba(209, 250, 229, 0.68);
|
color: color-mix(in srgb, var(--theme-primary-soft) 68%, transparent);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
@@ -653,11 +653,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setup-startup-step.is-success {
|
.setup-startup-step.is-success {
|
||||||
border-color: rgba(16, 185, 129, 0.32);
|
border-color: rgba(var(--theme-primary-rgb), 0.32);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-startup-step.is-success .pi {
|
.setup-startup-step.is-success .pi {
|
||||||
color: #34d399;
|
color: var(--theme-primary-light-5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-startup-step.is-error {
|
.setup-startup-step.is-error {
|
||||||
@@ -714,7 +714,7 @@
|
|||||||
.setup-page {
|
.setup-page {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top right, rgba(16, 185, 129, 0.2), transparent 22rem),
|
radial-gradient(circle at top right, rgba(var(--theme-primary-rgb), 0.2), transparent 22rem),
|
||||||
linear-gradient(180deg, #04110d 0%, #10281f 36%, #eef5f1 36%, #f6fbf8 100%);
|
linear-gradient(180deg, #04110d 0%, #10281f 36%, #eef5f1 36%, #f6fbf8 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.travel-calculator-field input:focus {
|
.travel-calculator-field input:focus {
|
||||||
border-color: rgba(59, 130, 246, 0.46);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.46);
|
||||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
box-shadow: 0 0 0 3px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.1);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
|
|
||||||
.composer-date-apply-btn {
|
.composer-date-apply-btn {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: linear-gradient(135deg, #22c55e, #10b981);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,9 +182,9 @@
|
|||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
padding: 0 8px 0 10px;
|
padding: 0 8px 0 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
border: 1px solid rgba(59, 130, 246, 0.28);
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.28);
|
||||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.14), rgba(16, 185, 129, 0.12));
|
background: linear-gradient(135deg, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.14), rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08));
|
||||||
color: #1d4ed8;
|
color: var(--theme-primary-active);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
flex: none;
|
flex: none;
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
|
|
||||||
.composer-biz-time-tag i {
|
.composer-biz-time-tag i {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #2563eb;
|
color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.composer-biz-time-tag-label {
|
.composer-biz-time-tag-label {
|
||||||
@@ -422,10 +422,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.send-btn {
|
.send-btn {
|
||||||
background: linear-gradient(135deg, #22c55e, #10b981);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: var(--wb-fs-tool-icon);
|
font-size: var(--wb-fs-tool-icon);
|
||||||
box-shadow: 0 8px 18px rgba(16, 185, 129, 0.18);
|
box-shadow: 0 8px 18px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
.send-btn:disabled {
|
.send-btn:disabled {
|
||||||
@@ -468,8 +468,8 @@
|
|||||||
height: 150px;
|
height: 150px;
|
||||||
border-radius: 0 0 0 140px;
|
border-radius: 0 0 0 140px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at 0 100%, rgba(16, 185, 129, 0.14), transparent 54%),
|
radial-gradient(circle at 0 100%, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.14), transparent 54%),
|
||||||
linear-gradient(135deg, rgba(16, 185, 129, 0.14), rgba(96, 165, 250, 0.06));
|
linear-gradient(135deg, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.14), rgba(96, 165, 250, 0.06));
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
@@ -502,11 +502,11 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(240, 253, 244, 0.95);
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.12);
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.16);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-insight-title-row {
|
.review-insight-title-row {
|
||||||
@@ -617,8 +617,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.intent-pill.draft {
|
.intent-pill.draft {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.intent-pill.approval {
|
.intent-pill.approval {
|
||||||
@@ -719,7 +719,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-side-intent-row i {
|
.review-side-intent-row i {
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,9 +765,9 @@
|
|||||||
|
|
||||||
.review-side-metric-card.editable:hover,
|
.review-side-metric-card.editable:hover,
|
||||||
.review-side-metric-card.editing {
|
.review-side-metric-card.editing {
|
||||||
border-color: rgba(16, 185, 129, 0.34);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.34);
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.08);
|
box-shadow: 0 4px 12px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,9 +786,9 @@
|
|||||||
|
|
||||||
.review-side-metric-card.editable:hover .review-side-metric-icon,
|
.review-side-metric-card.editable:hover .review-side-metric-icon,
|
||||||
.review-side-metric-card.editing .review-side-metric-icon {
|
.review-side-metric-card.editing .review-side-metric-icon {
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
border-color: rgba(16, 185, 129, 0.22);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.22);
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-side-metric-card.invalid .review-side-metric-icon {
|
.review-side-metric-card.invalid .review-side-metric-icon {
|
||||||
@@ -820,7 +820,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 34px;
|
min-height: 34px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.2);
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.2);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: rgba(255, 255, 255, 0.96);
|
background: rgba(255, 255, 255, 0.96);
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
@@ -844,8 +844,8 @@
|
|||||||
|
|
||||||
.review-inline-input:focus {
|
.review-inline-input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: rgba(16, 185, 129, 0.42);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.42);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.08);
|
box-shadow: 0 0 0 3px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-inline-select-list {
|
.review-inline-select-list {
|
||||||
@@ -869,9 +869,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-inline-select-option.active {
|
.review-inline-select-option.active {
|
||||||
border-color: rgba(16, 185, 129, 0.36);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.36);
|
||||||
background: rgba(240, 253, 244, 0.94);
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-inline-error {
|
.review-inline-error {
|
||||||
@@ -900,7 +900,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-side-edit-hint.upload {
|
.review-side-edit-hint.upload {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-side-metric-card:hover .review-side-edit-hint,
|
.review-side-metric-card:hover .review-side-edit-hint,
|
||||||
@@ -935,7 +935,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-side-confidence {
|
.review-side-confidence {
|
||||||
color: #10b981;
|
color: var(--success);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
@@ -961,9 +961,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-side-category-card.active {
|
.review-side-category-card.active {
|
||||||
border-color: rgba(52, 211, 153, 0.62);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.5);
|
||||||
background: rgba(240, 253, 244, 0.9);
|
background: var(--theme-primary-soft);
|
||||||
box-shadow: inset 0 0 0 1px rgba(16, 185, 129, 0.08);
|
box-shadow: inset 0 0 0 1px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-side-category-copy {
|
.review-side-category-copy {
|
||||||
@@ -988,7 +988,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-side-group-check {
|
.review-side-group-check {
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1014,9 +1014,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-other-category-option.active {
|
.review-other-category-option.active {
|
||||||
border-color: rgba(16, 185, 129, 0.36);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.36);
|
||||||
background: rgba(240, 253, 244, 0.94);
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-side-risk-card {
|
.review-side-risk-card {
|
||||||
@@ -1064,8 +1064,8 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: rgba(14, 165, 233, 0.12);
|
background: rgba(58, 124, 165, 0.12);
|
||||||
color: #0284c7;
|
color: #2f6d95;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1080,8 +1080,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-side-risk-item.low .review-side-risk-icon {
|
.review-side-risk-item.low .review-side-risk-icon {
|
||||||
background: rgba(14, 165, 233, 0.12);
|
background: rgba(58, 124, 165, 0.12);
|
||||||
color: #0284c7;
|
color: #2f6d95;
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-side-risk-copy {
|
.review-side-risk-copy {
|
||||||
@@ -1121,7 +1121,7 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
@@ -1173,10 +1173,10 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.22);
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.22);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(255, 255, 255, 0.94);
|
background: rgba(255, 255, 255, 0.94);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.08);
|
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.08);
|
||||||
@@ -1270,8 +1270,8 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(236, 253, 245, 0.92);
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
@@ -1296,9 +1296,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-document-meta-chip.confidence {
|
.review-document-meta-chip.confidence {
|
||||||
background: rgba(236, 253, 245, 0.92);
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success);
|
||||||
border-color: rgba(167, 243, 208, 0.92);
|
border-color: color-mix(in srgb, var(--success) 28%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-document-scroll {
|
.review-document-scroll {
|
||||||
@@ -1404,8 +1404,8 @@
|
|||||||
.review-document-edit-field input:focus,
|
.review-document-edit-field input:focus,
|
||||||
.review-document-edit-field textarea:focus {
|
.review-document-edit-field textarea:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: rgba(16, 185, 129, 0.36);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.36);
|
||||||
box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.08);
|
box-shadow: 0 0 0 4px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-document-edit-field textarea {
|
.review-document-edit-field textarea {
|
||||||
@@ -1482,8 +1482,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.knowledge-question-btn:hover:not(:disabled) {
|
.knowledge-question-btn:hover:not(:disabled) {
|
||||||
border-color: rgba(16, 185, 129, 0.3);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.3);
|
||||||
background: rgba(240, 253, 244, 0.9);
|
background: var(--theme-primary-soft);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1495,7 +1495,7 @@
|
|||||||
|
|
||||||
.knowledge-question-btn i {
|
.knowledge-question-btn i {
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.success {
|
.status-pill.success {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pill.warning {
|
.status-pill.warning {
|
||||||
@@ -94,9 +94,12 @@
|
|||||||
background: #cbd5e1;
|
background: #cbd5e1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-list li.done .timeline-dot,
|
.timeline-list li.done .timeline-dot {
|
||||||
|
background: var(--success);
|
||||||
|
}
|
||||||
|
|
||||||
.timeline-list li.current .timeline-dot {
|
.timeline-list li.current .timeline-dot {
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-list strong {
|
.timeline-list strong {
|
||||||
@@ -347,8 +350,8 @@
|
|||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.82) 0%, rgba(251, 248, 243, 0.82) 100%);
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.82) 0%, rgba(251, 248, 243, 0.82) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 已删除:review-alert-chip-row 相关样式(冗余气泡) */
|
/* 已删除 review-alert-chip-row 相关冗余样式 */
|
||||||
/* 已删除:主对话框中的风险提示(与右侧边栏重复,已移除) */
|
/* 已删除主对话框中的风险提示,避免与右侧栏重复 */
|
||||||
|
|
||||||
/* 风险提示样式已统一到 review-pending-item */
|
/* 风险提示样式已统一到 review-pending-item */
|
||||||
.review-risk-brief-list {
|
.review-risk-brief-list {
|
||||||
@@ -402,12 +405,12 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: rgba(236, 253, 245, 0.95);
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 风险级别的图标样式(已删除主对话框中的风险提示,保留样式备用) */
|
/* 风险级别图标样式保留备用 */
|
||||||
.review-pending-icon.high {
|
.review-pending-icon.high {
|
||||||
background: rgba(254, 226, 226, 0.95);
|
background: rgba(254, 226, 226, 0.95);
|
||||||
color: #dc2626;
|
color: #dc2626;
|
||||||
@@ -473,9 +476,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-pending-status.ready {
|
.review-pending-status.ready {
|
||||||
background: rgba(240, 253, 244, 0.96);
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success);
|
||||||
border: 1px solid #86efac;
|
border: 1px solid color-mix(in srgb, var(--success) 28%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-footer-actions {
|
.review-footer-actions {
|
||||||
@@ -507,10 +510,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-footer-btn.primary {
|
.review-footer-btn.primary {
|
||||||
border-color: rgba(16, 185, 129, 0.26);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.26);
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 6px 14px rgba(16, 185, 129, 0.16);
|
box-shadow: 0 6px 14px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.16);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-footer-btn:disabled {
|
.review-footer-btn:disabled {
|
||||||
@@ -555,10 +558,10 @@
|
|||||||
|
|
||||||
.review-inline-btn.primary,
|
.review-inline-btn.primary,
|
||||||
.primary-dialog-btn {
|
.primary-dialog-btn {
|
||||||
border: 1px solid rgba(16, 185, 129, 0.22);
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.22);
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 10px 22px rgba(16, 185, 129, 0.18);
|
box-shadow: 0 10px 22px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-inline-btn.secondary,
|
.review-inline-btn.secondary,
|
||||||
@@ -593,7 +596,7 @@
|
|||||||
|
|
||||||
.review-inline-guidance {
|
.review-inline-guidance {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
}
|
}
|
||||||
@@ -608,8 +611,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.review-status-banner.ready {
|
.review-status-banner.ready {
|
||||||
border-color: #bbf7d0;
|
border-color: color-mix(in srgb, var(--success) 28%, transparent);
|
||||||
background: linear-gradient(180deg, #f5fffa 0%, #ecfdf5 100%);
|
background: linear-gradient(180deg, #ffffff 0%, var(--success-soft) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-status-banner.pending {
|
.review-status-banner.pending {
|
||||||
@@ -921,8 +924,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.action-card.primary {
|
.action-card.primary {
|
||||||
border-color: #bbf7d0;
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.28);
|
||||||
background: #f0fdf4;
|
background: var(--theme-primary-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-card.secondary {
|
.action-card.secondary {
|
||||||
@@ -987,7 +990,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.recognition-bubble-label {
|
.recognition-bubble-label {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
@@ -1064,7 +1067,7 @@
|
|||||||
width: min(720px, calc(100vw - 40px));
|
width: min(720px, calc(100vw - 40px));
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top right, rgba(16, 185, 129, 0.08), transparent 28%),
|
radial-gradient(circle at top right, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08), transparent 28%),
|
||||||
linear-gradient(180deg, #fbfdff 0%, #f6f9fc 100%);
|
linear-gradient(180deg, #fbfdff 0%, #f6f9fc 100%);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 24px 80px rgba(15, 23, 42, 0.22),
|
0 24px 80px rgba(15, 23, 42, 0.22),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top right, rgba(16, 185, 129, 0.08), transparent 28%),
|
radial-gradient(circle at top right, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08), transparent 28%),
|
||||||
linear-gradient(180deg, #fbfdff 0%, #f6f9fc 100%);
|
linear-gradient(180deg, #fbfdff 0%, #f6f9fc 100%);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 24px 80px rgba(15, 23, 42, 0.22),
|
0 24px 80px rgba(15, 23, 42, 0.22),
|
||||||
@@ -109,14 +109,14 @@
|
|||||||
|
|
||||||
.welcome-quick-action-btn:hover:not(:disabled) {
|
.welcome-quick-action-btn:hover:not(:disabled) {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.1);
|
box-shadow: 0 4px 12px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome-quick-action-btn:hover:not(:disabled) i {
|
.welcome-quick-action-btn:hover:not(:disabled) i {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome-quick-action-btn:disabled {
|
.welcome-quick-action-btn:disabled {
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.welcome-card i {
|
.welcome-card i {
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
font-size: var(--wb-fs-welcome);
|
font-size: var(--wb-fs-welcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
transform: translateY(8px);
|
transform: translateY(8px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 笔记本 / 中等屏:工作台正文字号整体下调一档 */
|
/* 笔记本和中等屏:工作台正文字号整体下调一档 */
|
||||||
@media (max-width: 1680px) {
|
@media (max-width: 1680px) {
|
||||||
.assistant-modal-stage {
|
.assistant-modal-stage {
|
||||||
--wb-fs-title: 19px;
|
--wb-fs-title: 19px;
|
||||||
@@ -226,7 +226,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 大屏:左右分栏;右侧详情区宽度随视口收缩 */
|
/* 大屏:左右分栏,右侧详情区宽度随视口收缩 */
|
||||||
@media (min-width: 1441px) and (max-width: 1680px) {
|
@media (min-width: 1441px) and (max-width: 1680px) {
|
||||||
.insight-panel-shell {
|
.insight-panel-shell {
|
||||||
width: clamp(280px, 26vw, 360px);
|
width: clamp(280px, 26vw, 360px);
|
||||||
@@ -272,7 +272,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 矮屏笔记本(如 1366×768):压缩顶栏与间距,把高度留给对话列表 */
|
/* 矮屏笔记本:压缩顶部栏与间距,把高度留给对话列表 */
|
||||||
@media (max-height: 820px) {
|
@media (max-height: 820px) {
|
||||||
.assistant-modal-stage {
|
.assistant-modal-stage {
|
||||||
--wb-fs-title: 17px;
|
--wb-fs-title: 17px;
|
||||||
@@ -386,24 +386,6 @@
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-row,
|
|
||||||
.message-row.user {
|
|
||||||
grid-template-columns: 34px minmax(0, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-row.user .message-avatar {
|
|
||||||
order: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-row.user .message-bubble {
|
|
||||||
order: 0;
|
|
||||||
justify-self: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-suggested-actions {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.composer {
|
.composer {
|
||||||
padding: 0 16px 16px;
|
padding: 0 16px 16px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.assistant-overlay {
|
.assistant-overlay {
|
||||||
/* 距屏幕边 10–18px,随视口微调;高度用 dvh 适配笔记本浏览器工具栏 */
|
/* 距屏幕边缘 10-18px,随视口微调;高度使用 dvh 适配浏览器工具栏 */
|
||||||
--assistant-viewport-inset: clamp(10px, 1.25vmin, 18px);
|
--assistant-viewport-inset: clamp(10px, 1.25vmin, 18px);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
@@ -13,11 +13,10 @@
|
|||||||
padding: var(--assistant-viewport-inset);
|
padding: var(--assistant-viewport-inset);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at 18% 14%, rgba(16, 185, 129, 0.18), transparent 24%),
|
linear-gradient(180deg, rgba(239, 246, 255, 0.98) 0%, rgba(248, 250, 252, 0.98) 100%),
|
||||||
radial-gradient(circle at 82% 12%, rgba(59, 130, 246, 0.12), transparent 28%),
|
rgba(241, 245, 249, 0.98);
|
||||||
rgba(97, 110, 131, 0.34);
|
backdrop-filter: none;
|
||||||
backdrop-filter: blur(18px) saturate(1.02);
|
-webkit-backdrop-filter: none;
|
||||||
-webkit-backdrop-filter: blur(18px) saturate(1.02);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.assistant-modal {
|
.assistant-modal {
|
||||||
@@ -39,7 +38,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.assistant-modal-stage {
|
.assistant-modal-stage {
|
||||||
/* 工作台字号令牌:笔记本断点见文末 @media */
|
/* 工作台字号令牌:笔记本断点见后续 media */
|
||||||
--wb-fs-title: 22px;
|
--wb-fs-title: 22px;
|
||||||
--wb-fs-desc: 13px;
|
--wb-fs-desc: 13px;
|
||||||
--wb-fs-badge: 12px;
|
--wb-fs-badge: 12px;
|
||||||
@@ -70,14 +69,12 @@
|
|||||||
transform: none;
|
transform: none;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top right, rgba(16, 185, 129, 0.14), transparent 26%),
|
linear-gradient(180deg, #f8fbff 0%, #edf5ff 100%);
|
||||||
radial-gradient(circle at top left, rgba(59, 130, 246, 0.10), transparent 24%),
|
|
||||||
linear-gradient(180deg, rgba(241, 246, 245, 0.92) 0%, rgba(230, 237, 235, 0.88) 100%);
|
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 28px 72px rgba(15, 23, 42, 0.22),
|
0 28px 72px rgba(15, 23, 42, 0.22),
|
||||||
0 10px 28px rgba(15, 23, 42, 0.09),
|
0 10px 28px rgba(15, 23, 42, 0.09),
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.42);
|
inset 0 1px 0 rgba(255, 255, 255, 0.42);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.44);
|
border: 1px solid rgba(191, 219, 254, 0.88);
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
@@ -108,11 +105,11 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: linear-gradient(135deg, #22c55e, #10b981);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: var(--wb-fs-badge);
|
font-size: var(--wb-fs-badge);
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
box-shadow: 0 8px 16px rgba(16, 185, 129, 0.14);
|
box-shadow: 0 8px 16px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.14);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,16 +157,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.assistant-toggle-btn {
|
.assistant-toggle-btn {
|
||||||
border-color: rgba(16, 185, 129, 0.18);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18);
|
||||||
background: rgba(245, 252, 249, 0.96);
|
background: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
color: #166534;
|
color: var(--theme-primary-active);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
box-shadow: 0 8px 18px rgba(16, 185, 129, 0.1);
|
box-shadow: 0 8px 18px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.assistant-toggle-btn:hover:not(:disabled) {
|
.assistant-toggle-btn:hover:not(:disabled) {
|
||||||
background: rgba(236, 253, 245, 0.98);
|
background: var(--theme-primary-soft);
|
||||||
border-color: rgba(16, 185, 129, 0.28);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.28);
|
||||||
}
|
}
|
||||||
|
|
||||||
.assistant-toggle-btn:disabled,
|
.assistant-toggle-btn:disabled,
|
||||||
@@ -254,8 +251,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flow-status-chip.completed {
|
.flow-status-chip.completed {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.flow-status-chip.failed {
|
.flow-status-chip.failed {
|
||||||
@@ -337,7 +334,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flow-step-item.completed .flow-step-rail span {
|
.flow-step-item.completed .flow-step-rail span {
|
||||||
background: #10b981;
|
background: var(--success);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,13 +402,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flow-step-status.completed {
|
.flow-step-status.completed {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #059669;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.flow-step-status.running {
|
.flow-step-status.running {
|
||||||
background: #eff6ff;
|
background: var(--theme-primary-soft);
|
||||||
color: #2563eb;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.flow-step-status.failed {
|
.flow-step-status.failed {
|
||||||
@@ -497,13 +494,13 @@
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
border: 1px solid rgba(189, 201, 214, 0.74);
|
border: 1px solid rgba(189, 201, 214, 0.74);
|
||||||
border-radius: 24px;
|
border-radius: 16px;
|
||||||
background: rgba(248, 251, 251, 0.84);
|
background: #ffffff;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 14px 32px rgba(148, 163, 184, 0.16),
|
0 14px 32px rgba(148, 163, 184, 0.16),
|
||||||
0 2px 6px rgba(15, 23, 42, 0.05);
|
0 2px 6px rgba(15, 23, 42, 0.05);
|
||||||
backdrop-filter: blur(22px);
|
backdrop-filter: none;
|
||||||
-webkit-backdrop-filter: blur(22px);
|
-webkit-backdrop-filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-panel {
|
.dialog-panel {
|
||||||
@@ -512,8 +509,7 @@
|
|||||||
grid-template-rows: auto minmax(0, 1fr) auto;
|
grid-template-rows: auto minmax(0, 1fr) auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top right, rgba(59, 130, 246, 0.07), transparent 22%),
|
linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
|
||||||
linear-gradient(180deg, rgba(252, 253, 253, 0.88) 0%, rgba(243, 247, 248, 0.84) 100%);
|
|
||||||
transition:
|
transition:
|
||||||
transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
|
transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
|
||||||
box-shadow 320ms cubic-bezier(0.22, 1, 0.36, 1);
|
box-shadow 320ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
@@ -564,18 +560,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.shortcut-chip i {
|
.shortcut-chip i {
|
||||||
color: #059669;
|
color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortcut-chip.active {
|
.shortcut-chip.active {
|
||||||
border-color: rgba(5, 150, 105, 0.38);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.38);
|
||||||
background: rgba(16, 185, 129, 0.1);
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortcut-chip.active i {
|
.shortcut-chip.active i {
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortcut-chip:disabled {
|
.shortcut-chip:disabled {
|
||||||
@@ -593,17 +589,6 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 38px minmax(0, 1fr);
|
|
||||||
align-items: start;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-row.user {
|
|
||||||
grid-template-columns: minmax(0, 1fr) 38px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-row.user .message-avatar {
|
.message-row.user .message-avatar {
|
||||||
order: 2;
|
order: 2;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@@ -850,13 +835,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.application-preview-row.highlight .application-preview-label {
|
.application-preview-row.highlight .application-preview-label {
|
||||||
background: #f0fdf4;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.application-preview-row.highlight .application-preview-value {
|
.application-preview-row.highlight .application-preview-value {
|
||||||
background: #f7fee7;
|
background: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
color: #166534;
|
color: var(--theme-primary-active);
|
||||||
font-weight: 780;
|
font-weight: 780;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1138,9 +1123,9 @@
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: #f1f5f9;
|
background: #f1f5f9;
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
box-shadow: inset 0 0 0 1px rgba(15, 118, 110, 0.08);
|
box-shadow: inset 0 0 0 1px rgba(var(--theme-primary-rgb), 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-suggested-action-copy {
|
.message-suggested-action-copy {
|
||||||
@@ -1171,7 +1156,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.message-suggested-action-btn:hover:not(:disabled) {
|
.message-suggested-action-btn:hover:not(:disabled) {
|
||||||
border-color: rgba(20, 184, 166, 0.72);
|
border-color: rgba(var(--theme-primary-rgb), 0.42);
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.09);
|
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.09);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
@@ -1179,35 +1164,35 @@
|
|||||||
|
|
||||||
.message-suggested-action-btn:hover:not(:disabled) .message-suggested-action-icon,
|
.message-suggested-action-btn:hover:not(:disabled) .message-suggested-action-icon,
|
||||||
.message-suggested-action-btn:focus-visible .message-suggested-action-icon {
|
.message-suggested-action-btn:focus-visible .message-suggested-action-icon {
|
||||||
background: #ccfbf1;
|
background: var(--theme-primary-soft);
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-suggested-action-btn:hover:not(:disabled) .message-suggested-action-arrow,
|
.message-suggested-action-btn:hover:not(:disabled) .message-suggested-action-arrow,
|
||||||
.message-suggested-action-btn:focus-visible .message-suggested-action-arrow {
|
.message-suggested-action-btn:focus-visible .message-suggested-action-arrow {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
transform: translateX(2px);
|
transform: translateX(2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-suggested-action-btn:focus-visible {
|
.message-suggested-action-btn:focus-visible {
|
||||||
outline: 3px solid rgba(20, 184, 166, 0.18);
|
outline: 3px solid var(--theme-focus-ring);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
border-color: #14b8a6;
|
border-color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-suggested-action-btn.selected {
|
.message-suggested-action-btn.selected {
|
||||||
border-color: rgba(13, 148, 136, 0.78);
|
border-color: rgba(var(--theme-primary-rgb), 0.52);
|
||||||
background: #f0fdfa;
|
background: var(--theme-primary-light-9);
|
||||||
box-shadow: inset 0 0 0 1px rgba(13, 148, 136, 0.18);
|
box-shadow: inset 0 0 0 1px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-suggested-action-btn.selected .message-suggested-action-icon {
|
.message-suggested-action-btn.selected .message-suggested-action-icon {
|
||||||
background: #99f6e4;
|
background: var(--theme-primary-soft-strong);
|
||||||
color: #115e59;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-suggested-action-btn.selected .message-suggested-action-arrow {
|
.message-suggested-action-btn.selected .message-suggested-action-arrow {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-suggested-action-btn.locked:not(.selected) {
|
.message-suggested-action-btn.locked:not(.selected) {
|
||||||
@@ -1268,8 +1253,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.message-action-chip {
|
.message-action-chip {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-detail-block {
|
.message-detail-block {
|
||||||
@@ -1376,8 +1361,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.expense-query-summary-chip.completed {
|
.expense-query-summary-chip.completed {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #15803d;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.expense-query-summary-chip.other {
|
.expense-query-summary-chip.other {
|
||||||
@@ -1491,8 +1476,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.expense-query-record-status.completed {
|
.expense-query-record-status.completed {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #15803d;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.expense-query-record-card p {
|
.expense-query-record-card p {
|
||||||
@@ -1801,10 +1786,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tool-btn.composer-side-btn.active {
|
.tool-btn.composer-side-btn.active {
|
||||||
border-color: rgba(59, 130, 246, 0.42);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.42);
|
||||||
background: rgba(239, 246, 255, 0.96);
|
background: var(--theme-primary-soft);
|
||||||
color: #2563eb;
|
color: var(--theme-primary-active);
|
||||||
box-shadow: 0 6px 14px rgba(59, 130, 246, 0.14);
|
box-shadow: 0 6px 14px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
.composer-date-popover {
|
.composer-date-popover {
|
||||||
|
|||||||
@@ -51,8 +51,8 @@
|
|||||||
width: 6px;
|
width: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #10b981;
|
background: var(--success);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.12);
|
box-shadow: 0 0 0 3px rgba(var(--success-rgb), 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.validation-section--risk .validation-section-title {
|
.validation-section--risk .validation-section-title {
|
||||||
@@ -69,13 +69,13 @@
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 0 0 18px;
|
padding: 0 0 0 18px;
|
||||||
color: #0f766e;
|
color: var(--success-hover);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.55;
|
line-height: 1.55;
|
||||||
}
|
}
|
||||||
|
|
||||||
.validation-list li::marker {
|
.validation-list li::marker {
|
||||||
color: #14b8a6;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.validation-section--risk .risk-advice-list {
|
.validation-section--risk .risk-advice-list {
|
||||||
@@ -383,7 +383,7 @@
|
|||||||
padding: 18px;
|
padding: 18px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background:
|
background:
|
||||||
linear-gradient(180deg, rgba(240, 253, 244, .5) 0%, rgba(255, 255, 255, 0) 140px),
|
linear-gradient(180deg, color-mix(in srgb, var(--theme-primary-soft) 55%, transparent) 0%, rgba(255, 255, 255, 0) 140px),
|
||||||
#fff;
|
#fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,8 +415,8 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,9 +471,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ai-composer-surface:focus-within {
|
.ai-composer-surface:focus-within {
|
||||||
border-color: rgba(16, 185, 129, .58);
|
border-color: rgba(var(--theme-primary-rgb), .58);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, .11), 0 10px 24px rgba(15, 23, 42, .06);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring), 0 10px 24px rgba(15, 23, 42, .06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ai-composer textarea {
|
.ai-composer textarea {
|
||||||
@@ -552,14 +552,14 @@
|
|||||||
|
|
||||||
.ai-send-btn {
|
.ai-send-btn {
|
||||||
border: 0;
|
border: 0;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 18px rgba(16, 185, 129, .20);
|
box-shadow: 0 8px 18px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ai-send-btn:hover {
|
.ai-send-btn:hover {
|
||||||
background: #0ea672;
|
background: var(--theme-primary-active);
|
||||||
box-shadow: 0 10px 22px rgba(16, 185, 129, .24);
|
box-shadow: 0 10px 22px rgba(var(--theme-primary-rgb), .24);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ai-upload-btn:active,
|
.ai-upload-btn:active,
|
||||||
@@ -650,7 +650,7 @@
|
|||||||
|
|
||||||
.ai-preview-empty i {
|
.ai-preview-empty i {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
color: #10b981;
|
color: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ai-preview-actions {
|
.ai-preview-actions {
|
||||||
@@ -681,10 +681,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ai-preview-primary {
|
.ai-preview-primary {
|
||||||
border: 1px solid #059669;
|
border: 1px solid var(--theme-primary);
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 20px rgba(5, 150, 105, .18);
|
box-shadow: 0 8px 20px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ai-preview-secondary:hover {
|
.ai-preview-secondary:hover {
|
||||||
@@ -692,7 +692,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ai-preview-primary:hover {
|
.ai-preview-primary:hover {
|
||||||
background: #047857;
|
background: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ai-preview-secondary:disabled,
|
.ai-preview-secondary:disabled,
|
||||||
@@ -957,7 +957,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.validation-pill.ready {
|
.validation-pill.ready {
|
||||||
background: #f0fdf4;
|
background: var(--success-soft);
|
||||||
border-color: #bbf7d0;
|
border-color: var(--success-line);
|
||||||
color: #166534;
|
color: var(--success-active);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,9 +112,9 @@
|
|||||||
min-height: 24px;
|
min-height: 24px;
|
||||||
padding: 0 9px;
|
padding: 0 9px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
border: 1px solid rgba(16, 185, 129, .16);
|
border: 1px solid rgba(var(--theme-primary-rgb), .16);
|
||||||
color: #10b981;
|
color: var(--theme-primary-active);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -265,8 +265,8 @@
|
|||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 4px rgba(16, 185, 129, .12);
|
box-shadow: 0 0 0 4px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-line {
|
.progress-line {
|
||||||
@@ -309,7 +309,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,20 +346,20 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
inset: -4px;
|
inset: -4px;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
border: 2px solid rgba(16, 185, 129, .42);
|
border: 2px solid rgba(var(--theme-primary-rgb), .42);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.active span {
|
.progress-step.active span {
|
||||||
background: #059669;
|
background: var(--theme-primary-active);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.current span {
|
.progress-step.current span {
|
||||||
background: #10b981 !important;
|
background: var(--theme-primary) !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
box-shadow: 0 0 0 4px rgba(16, 185, 129, .15) !important;
|
box-shadow: 0 0 0 4px var(--theme-focus-ring) !important;
|
||||||
animation: breathe-dot 3.2s ease-in-out infinite !important;
|
animation: breathe-dot 3.2s ease-in-out infinite !important;
|
||||||
transform-origin: center !important;
|
transform-origin: center !important;
|
||||||
}
|
}
|
||||||
@@ -367,11 +367,11 @@
|
|||||||
@keyframes breathe-dot {
|
@keyframes breathe-dot {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
box-shadow: 0 4px 12px rgba(16, 185, 129, .3), 0 0 0 4px rgba(16, 185, 129, .15);
|
box-shadow: 0 4px 12px rgba(var(--theme-primary-rgb), .3), 0 0 0 4px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
transform: scale(1.12);
|
transform: scale(1.12);
|
||||||
box-shadow: 0 4px 20px rgba(16, 185, 129, .5), 0 0 0 10px rgba(16, 185, 129, .08);
|
box-shadow: 0 4px 20px rgba(var(--theme-primary-rgb), .5), 0 0 0 10px rgba(var(--theme-primary-rgb), .08);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,7 +382,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.current strong { color: #059669; }
|
.progress-step.current strong { color: var(--theme-primary-active); }
|
||||||
|
|
||||||
.progress-step-copy {
|
.progress-step-copy {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -414,16 +414,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.done .progress-step-status {
|
.progress-step.done .progress-step-status {
|
||||||
border-color: rgba(16, 185, 129, .2);
|
border-color: rgba(var(--theme-primary-rgb), .2);
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.current .progress-step-status {
|
.progress-step.current .progress-step-status {
|
||||||
border-color: rgba(5, 150, 105, .22);
|
border-color: rgba(var(--theme-primary-rgb), .22);
|
||||||
background: #059669;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 8px 18px rgba(5, 150, 105, .14);
|
box-shadow: 0 8px 18px var(--theme-primary-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step:not(.done):not(.current) .progress-step-status {
|
.progress-step:not(.done):not(.current) .progress-step-status {
|
||||||
@@ -432,7 +432,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.progress-step.current small {
|
.progress-step.current small {
|
||||||
color: #059669;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-step-meta {
|
.progress-step-meta {
|
||||||
@@ -535,14 +535,14 @@
|
|||||||
|
|
||||||
.smart-entry-btn.secondary {
|
.smart-entry-btn.secondary {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
border-color: rgba(16, 185, 129, .24);
|
border-color: rgba(var(--theme-primary-rgb), .24);
|
||||||
}
|
}
|
||||||
|
|
||||||
.smart-entry-btn:hover {
|
.smart-entry-btn:hover {
|
||||||
border-color: rgba(16, 185, 129, .36);
|
border-color: rgba(var(--theme-primary-rgb), .36);
|
||||||
background: #f0fdf4;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-total {
|
.detail-total {
|
||||||
@@ -553,8 +553,8 @@
|
|||||||
min-height: 34px;
|
min-height: 34px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
@@ -643,16 +643,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.application-detail-fact.highlight span {
|
.application-detail-fact.highlight span {
|
||||||
background: #eefcf6;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.application-detail-fact.highlight strong {
|
.application-detail-fact.highlight strong {
|
||||||
background: #f6fef9;
|
background: color-mix(in srgb, var(--theme-primary-soft) 55%, #ffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
.application-detail-fact.emphasis strong {
|
.application-detail-fact.emphasis strong {
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,13 +663,13 @@
|
|||||||
|
|
||||||
.detail-note-editor textarea {
|
.detail-note-editor textarea {
|
||||||
min-height: 92px;
|
min-height: 92px;
|
||||||
border-color: rgba(16, 185, 129, .28);
|
border-color: rgba(var(--theme-primary-rgb), .28);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-note-editor textarea:focus {
|
.detail-note-editor textarea:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, .12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,8 +692,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.leader-approval-card {
|
.leader-approval-card {
|
||||||
border-color: rgba(5, 150, 105, .18);
|
border-color: rgba(var(--theme-primary-rgb), .18);
|
||||||
background: linear-gradient(180deg, #ffffff 0%, #f7fdfb 100%);
|
background: linear-gradient(180deg, #ffffff 0%, var(--theme-primary-soft) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.leader-approval-card textarea {
|
.leader-approval-card textarea {
|
||||||
@@ -704,8 +704,8 @@
|
|||||||
|
|
||||||
.leader-approval-card textarea:focus {
|
.leader-approval-card textarea:focus {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
border-color: rgba(5, 150, 105, .5);
|
border-color: rgba(var(--theme-primary-rgb), .5);
|
||||||
box-shadow: 0 0 0 3px rgba(5, 150, 105, .1);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.leader-opinion-meta {
|
.leader-opinion-meta {
|
||||||
@@ -721,7 +721,7 @@
|
|||||||
|
|
||||||
.leader-opinion-meta strong {
|
.leader-opinion-meta strong {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,7 +758,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.application-leader-opinion-head strong {
|
.application-leader-opinion-head strong {
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
@@ -812,12 +812,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detail-expense-table tbody tr.system-generated-row td {
|
.detail-expense-table tbody tr.system-generated-row td {
|
||||||
background: #f0fdf4;
|
background: var(--success-soft);
|
||||||
border-bottom-color: #bbf7d0;
|
border-bottom-color: var(--success-line);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-expense-table tbody tr.system-generated-row:hover td {
|
.detail-expense-table tbody tr.system-generated-row:hover td {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-expense-table .col-time { width: 11%; }
|
.detail-expense-table .col-time { width: 11%; }
|
||||||
@@ -893,8 +893,8 @@
|
|||||||
|
|
||||||
.editor-input:focus,
|
.editor-input:focus,
|
||||||
.editor-select:focus {
|
.editor-select:focus {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, .12);
|
box-shadow: 0 0 0 3px var(--theme-focus-ring);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,8 +966,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.over-tag.system {
|
.over-tag.system {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.expense-total-under-table {
|
.expense-total-under-table {
|
||||||
@@ -977,10 +977,10 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
border: 1px solid #d1fae5;
|
border: 1px solid rgba(var(--theme-primary-rgb), .22);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #f0fdf4;
|
background: var(--theme-primary-soft);
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.expense-total-under-table span {
|
.expense-total-under-table span {
|
||||||
@@ -990,7 +990,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.expense-total-under-table strong {
|
.expense-total-under-table strong {
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
@@ -1050,8 +1050,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.attachment-recognition-pill.pass {
|
.attachment-recognition-pill.pass {
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment-recognition-pill.medium {
|
.attachment-recognition-pill.medium {
|
||||||
@@ -1101,9 +1101,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-action.upload {
|
.icon-action.upload {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
border-color: rgba(16, 185, 129, .24);
|
border-color: rgba(var(--theme-primary-rgb), .24);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-action.preview {
|
.icon-action.preview {
|
||||||
@@ -1133,14 +1133,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.inline-action.accent {
|
.inline-action.accent {
|
||||||
border-color: rgba(16, 185, 129, .24);
|
border-color: rgba(var(--theme-primary-rgb), .24);
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.inline-action.primary {
|
.inline-action.primary {
|
||||||
border-color: #10b981;
|
border-color: var(--theme-primary);
|
||||||
background: #10b981;
|
background: var(--theme-primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1151,13 +1151,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.inline-action:hover {
|
.inline-action:hover {
|
||||||
border-color: rgba(16, 185, 129, .36);
|
border-color: rgba(var(--theme-primary-rgb), .36);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.inline-action.primary:hover {
|
.inline-action.primary:hover {
|
||||||
border-color: #059669;
|
border-color: var(--theme-primary-active);
|
||||||
background: #059669;
|
background: var(--theme-primary-active);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1179,8 +1179,8 @@
|
|||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
padding: 0 9px;
|
padding: 0 9px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -1194,8 +1194,8 @@
|
|||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
padding: 0 9px;
|
padding: 0 9px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #ecfdf5;
|
background: var(--success-soft);
|
||||||
color: #047857;
|
color: var(--success-hover);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -1217,7 +1217,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.risk-inline-tag.pass,
|
.risk-inline-tag.pass,
|
||||||
.risk-inline-tag.low { background: #ecfdf5; color: #059669; }
|
.risk-inline-tag.low { background: var(--success-soft); color: var(--success-hover); }
|
||||||
.risk-inline-tag.medium { background: #fff7ed; color: #ea580c; }
|
.risk-inline-tag.medium { background: #fff7ed; color: #ea580c; }
|
||||||
.risk-inline-tag.high { background: #fef2f2; color: #dc2626; }
|
.risk-inline-tag.high { background: #fef2f2; color: #dc2626; }
|
||||||
|
|
||||||
@@ -1248,7 +1248,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.risk-suggestion {
|
.risk-suggestion {
|
||||||
color: #0f766e;
|
color: var(--success-hover);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1284,10 +1284,10 @@
|
|||||||
grid-template-rows: auto minmax(0, 1fr);
|
grid-template-rows: auto minmax(0, 1fr);
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 22px;
|
padding: 22px;
|
||||||
border: 1px solid rgba(16, 185, 129, .14);
|
border: 1px solid rgba(var(--theme-primary-rgb), .14);
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top left, rgba(16, 185, 129, .12), transparent 36%),
|
radial-gradient(circle at top left, rgba(var(--theme-primary-rgb), .12), transparent 36%),
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, .98), rgba(247, 250, 252, .98));
|
linear-gradient(180deg, rgba(255, 255, 255, .98), rgba(247, 250, 252, .98));
|
||||||
box-shadow: 0 28px 56px rgba(15, 23, 42, .2);
|
box-shadow: 0 28px 56px rgba(15, 23, 42, .2);
|
||||||
}
|
}
|
||||||
@@ -1338,8 +1338,8 @@
|
|||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(16, 185, 129, .12);
|
background: var(--theme-primary-soft);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -1547,10 +1547,10 @@
|
|||||||
|
|
||||||
.approve-action {
|
.approve-action {
|
||||||
min-width: 92px;
|
min-width: 92px;
|
||||||
border: 1px solid #059669;
|
border: 1px solid var(--success);
|
||||||
background: #059669;
|
background: var(--success);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 4px 10px rgba(5, 150, 105, .14);
|
box-shadow: 0 4px 10px rgba(var(--success-rgb), .14);
|
||||||
}
|
}
|
||||||
|
|
||||||
.reject-action {
|
.reject-action {
|
||||||
|
|||||||
334
web/src/components/audit/AuditAssetList.vue
Normal file
334
web/src/components/audit/AuditAssetList.vue
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
<template>
|
||||||
|
<article class="skill-list panel">
|
||||||
|
<nav class="status-tabs" aria-label="能力类型">
|
||||||
|
<button
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.id"
|
||||||
|
type="button"
|
||||||
|
:class="{ active: activeType === tab.id }"
|
||||||
|
@click="emit('update:activeType', tab.id)"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="list-toolbar">
|
||||||
|
<div class="filter-set">
|
||||||
|
<label class="search-filter">
|
||||||
|
<i class="mdi mdi-magnify"></i>
|
||||||
|
<input
|
||||||
|
:value="keyword"
|
||||||
|
type="search"
|
||||||
|
:placeholder="searchPlaceholder"
|
||||||
|
@input="emit('update:keyword', $event.target.value)"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<AuditPickerFilter
|
||||||
|
id="domain"
|
||||||
|
title="选择业务域"
|
||||||
|
close-label="关闭业务域选择"
|
||||||
|
:active-filter-popover="activeFilterPopover"
|
||||||
|
:label="selectedDomainLabel"
|
||||||
|
:options="domainOptions"
|
||||||
|
:selected-value="selectedDomain"
|
||||||
|
@toggle="emit('toggle-filter-popover', $event)"
|
||||||
|
@close="emit('close-filter-popover')"
|
||||||
|
@select="selectFilter('domain', $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AuditPickerFilter
|
||||||
|
v-if="showOwnerFilter"
|
||||||
|
id="owner"
|
||||||
|
title="选择负责人"
|
||||||
|
close-label="关闭负责人选择"
|
||||||
|
:active-filter-popover="activeFilterPopover"
|
||||||
|
:label="selectedOwnerLabel"
|
||||||
|
:options="ownerOptions"
|
||||||
|
:selected-value="selectedOwner"
|
||||||
|
@toggle="emit('toggle-filter-popover', $event)"
|
||||||
|
@close="emit('close-filter-popover')"
|
||||||
|
@select="selectFilter('owner', $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AuditPickerFilter
|
||||||
|
v-if="showRiskLevelFilter"
|
||||||
|
id="riskLevel"
|
||||||
|
title="选择风险等级"
|
||||||
|
close-label="关闭风险等级选择"
|
||||||
|
:active-filter-popover="activeFilterPopover"
|
||||||
|
:label="selectedRiskLevelLabel"
|
||||||
|
:options="riskLevelOptions"
|
||||||
|
:selected-value="selectedRiskLevel"
|
||||||
|
@toggle="emit('toggle-filter-popover', $event)"
|
||||||
|
@close="emit('close-filter-popover')"
|
||||||
|
@select="selectFilter('riskLevel', $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AuditPickerFilter
|
||||||
|
v-if="showRiskScenarioFilter"
|
||||||
|
id="riskScenario"
|
||||||
|
title="选择使用场景"
|
||||||
|
close-label="关闭使用场景选择"
|
||||||
|
:active-filter-popover="activeFilterPopover"
|
||||||
|
:label="selectedRiskScenarioLabel"
|
||||||
|
:options="riskScenarioOptions"
|
||||||
|
:selected-value="selectedRiskScenario"
|
||||||
|
@toggle="emit('toggle-filter-popover', $event)"
|
||||||
|
@close="emit('close-filter-popover')"
|
||||||
|
@select="selectFilter('riskScenario', $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AuditPickerFilter
|
||||||
|
v-if="showOnlineFilter"
|
||||||
|
id="online"
|
||||||
|
title="选择上线状态"
|
||||||
|
close-label="关闭上线状态选择"
|
||||||
|
:active-filter-popover="activeFilterPopover"
|
||||||
|
:label="selectedOnlineStateLabel"
|
||||||
|
:options="onlineStateOptions"
|
||||||
|
:selected-value="selectedOnlineState"
|
||||||
|
@toggle="emit('toggle-filter-popover', $event)"
|
||||||
|
@close="emit('close-filter-popover')"
|
||||||
|
@select="selectFilter('online', $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AuditPickerFilter
|
||||||
|
v-if="showEnabledFilter"
|
||||||
|
id="enabled"
|
||||||
|
title="选择启用状态"
|
||||||
|
close-label="关闭启用状态选择"
|
||||||
|
:active-filter-popover="activeFilterPopover"
|
||||||
|
:label="selectedEnabledStateLabel"
|
||||||
|
:options="enabledStateOptions"
|
||||||
|
:selected-value="selectedEnabledState"
|
||||||
|
@toggle="emit('toggle-filter-popover', $event)"
|
||||||
|
@close="emit('close-filter-popover')"
|
||||||
|
@select="selectFilter('enabled', $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AuditPickerFilter
|
||||||
|
v-if="showStatusFilter"
|
||||||
|
id="status"
|
||||||
|
title="选择状态"
|
||||||
|
close-label="关闭状态选择"
|
||||||
|
:active-filter-popover="activeFilterPopover"
|
||||||
|
:label="selectedStatusLabel"
|
||||||
|
:options="statusOptions"
|
||||||
|
:selected-value="selectedStatus"
|
||||||
|
@toggle="emit('toggle-filter-popover', $event)"
|
||||||
|
@close="emit('close-filter-popover')"
|
||||||
|
@select="selectFilter('status', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="toolbar-actions">
|
||||||
|
<button
|
||||||
|
v-if="activeFilterTokens.length"
|
||||||
|
class="ghost-filter-btn"
|
||||||
|
type="button"
|
||||||
|
@click="emit('reset-filters')"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-filter-remove-outline"></i>
|
||||||
|
<span>清空筛选</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="create-btn"
|
||||||
|
type="button"
|
||||||
|
:disabled="!canCreateRiskRule"
|
||||||
|
@click="emit('create-risk-rule')"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-plus"></i>
|
||||||
|
<span>{{ createButtonLabel }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="hint"><i class="mdi mdi-information-outline"></i> {{ hintText }}</p>
|
||||||
|
|
||||||
|
<div v-if="activeFilterTokens.length" class="active-filter-strip">
|
||||||
|
<span v-for="token in activeFilterTokens" :key="token" class="active-filter-chip">
|
||||||
|
{{ token }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="table-wrap"
|
||||||
|
:class="{ 'is-empty': !loading && !errorMessage && !visibleSkills.length }"
|
||||||
|
>
|
||||||
|
<div v-if="loading" class="table-state">
|
||||||
|
<TableLoadingState
|
||||||
|
variant="panel"
|
||||||
|
:title="`${activeTabLabel}资产同步中`"
|
||||||
|
:message="`正在加载${activeTabLabel}资产`"
|
||||||
|
icon="mdi mdi-view-list-outline"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="errorMessage" class="table-state error">
|
||||||
|
<i class="mdi mdi-alert-circle-outline"></i>
|
||||||
|
<p>{{ errorMessage }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TableEmptyState
|
||||||
|
v-else-if="!visibleSkills.length"
|
||||||
|
:eyebrow="auditEmptyState.eyebrow"
|
||||||
|
:title="auditEmptyState.title"
|
||||||
|
:description="auditEmptyState.desc"
|
||||||
|
:icon="auditEmptyState.icon"
|
||||||
|
:action-label="auditEmptyState.actionLabel"
|
||||||
|
:action-icon="auditEmptyState.actionIcon"
|
||||||
|
:tone="auditEmptyState.tone"
|
||||||
|
:art-label="auditEmptyState.artLabel"
|
||||||
|
:tips="auditEmptyState.tips"
|
||||||
|
@action="emit('empty-action')"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<table v-else>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ tableColumns.name }}</th>
|
||||||
|
<th>{{ tableColumns.category }}</th>
|
||||||
|
<th>{{ tableColumns.owner }}</th>
|
||||||
|
<th>{{ tableColumns.scope }}</th>
|
||||||
|
<th v-if="showRuntimeColumn">{{ tableColumns.runtime }}</th>
|
||||||
|
<th v-if="showVersionColumn">{{ tableColumns.version }}</th>
|
||||||
|
<th v-if="showStatusColumn">{{ tableColumns.status || '状态' }}</th>
|
||||||
|
<th v-if="showMetricColumn">{{ tableColumns.metric }}</th>
|
||||||
|
<th v-if="showOnlineColumn">是否上线</th>
|
||||||
|
<th v-if="showEnabledColumn">是否启用</th>
|
||||||
|
<th>{{ tableColumns.updatedAt || '最近更新' }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="skill in visibleSkills"
|
||||||
|
:key="skill.id"
|
||||||
|
:class="{ 'is-disabled': skill.usesJsonRiskRule && skill.statusValue === 'generating' }"
|
||||||
|
@click="emit('open-asset-detail', skill)"
|
||||||
|
>
|
||||||
|
<td>
|
||||||
|
<div class="skill-name-cell">
|
||||||
|
<span class="skill-avatar" :class="skill.badgeTone">{{ skill.short }}</span>
|
||||||
|
<div>
|
||||||
|
<strong>{{ skill.name }}</strong>
|
||||||
|
<span class="skill-list-subtitle">{{ skill.listSubtitle || skill.summary }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>{{ skill.category }}</td>
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
v-if="skill.usesJsonRiskRule"
|
||||||
|
class="json-risk-meta-badge"
|
||||||
|
:class="skill.riskLevelTone"
|
||||||
|
>
|
||||||
|
{{ skill.riskLevelLabel || '-' }}
|
||||||
|
</span>
|
||||||
|
<template v-else>{{ skill.owner }}</template>
|
||||||
|
</td>
|
||||||
|
<td><span class="scope-pill">{{ skill.scope }}</span></td>
|
||||||
|
<td v-if="showRuntimeColumn">{{ skill.model }}</td>
|
||||||
|
<td v-if="showVersionColumn">{{ skill.versionDisplay || skill.version }}</td>
|
||||||
|
<td v-if="showStatusColumn">
|
||||||
|
<span class="status-pill" :class="skill.statusTone">{{ skill.status }}</span>
|
||||||
|
</td>
|
||||||
|
<td v-if="showMetricColumn">{{ skill.hitRate }}</td>
|
||||||
|
<td v-if="showOnlineColumn">
|
||||||
|
<span class="status-pill" :class="skill.isOnlineTone">{{ skill.isOnlineLabel }}</span>
|
||||||
|
</td>
|
||||||
|
<td v-if="showEnabledColumn">
|
||||||
|
<span class="status-pill" :class="skill.isEnabledTone">{{ skill.isEnabledLabel }}</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ skill.updatedAt }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer v-if="!loading && !errorMessage && visibleSkills.length" class="list-foot">
|
||||||
|
<span class="page-summary">当前展示 {{ visibleSkills.length }} 条资产</span>
|
||||||
|
</footer>
|
||||||
|
</article>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import AuditPickerFilter from './AuditPickerFilter.vue'
|
||||||
|
import TableEmptyState from '../shared/TableEmptyState.vue'
|
||||||
|
import TableLoadingState from '../shared/TableLoadingState.vue'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'AuditAssetList'
|
||||||
|
})
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
tabs: { type: Array, default: () => [] },
|
||||||
|
activeType: { type: String, default: '' },
|
||||||
|
activeTabLabel: { type: String, default: '' },
|
||||||
|
keyword: { type: String, default: '' },
|
||||||
|
searchPlaceholder: { type: String, default: '' },
|
||||||
|
createButtonLabel: { type: String, default: '' },
|
||||||
|
hintText: { type: String, default: '' },
|
||||||
|
tableColumns: { type: Object, default: () => ({}) },
|
||||||
|
showRuntimeColumn: { type: Boolean, default: false },
|
||||||
|
showVersionColumn: { type: Boolean, default: false },
|
||||||
|
showMetricColumn: { type: Boolean, default: false },
|
||||||
|
showStatusColumn: { type: Boolean, default: false },
|
||||||
|
showOnlineColumn: { type: Boolean, default: false },
|
||||||
|
showEnabledColumn: { type: Boolean, default: false },
|
||||||
|
visibleSkills: { type: Array, default: () => [] },
|
||||||
|
auditEmptyState: { type: Object, default: () => ({}) },
|
||||||
|
loading: { type: Boolean, default: false },
|
||||||
|
errorMessage: { type: String, default: '' },
|
||||||
|
selectedDomain: { type: String, default: '' },
|
||||||
|
selectedOwner: { type: String, default: '' },
|
||||||
|
selectedRiskLevel: { type: String, default: '' },
|
||||||
|
selectedStatus: { type: String, default: '' },
|
||||||
|
selectedRiskScenario: { type: String, default: '' },
|
||||||
|
selectedOnlineState: { type: String, default: '' },
|
||||||
|
selectedEnabledState: { type: String, default: '' },
|
||||||
|
selectedDomainLabel: { type: String, default: '' },
|
||||||
|
selectedOwnerLabel: { type: String, default: '' },
|
||||||
|
selectedRiskLevelLabel: { type: String, default: '' },
|
||||||
|
selectedStatusLabel: { type: String, default: '' },
|
||||||
|
selectedRiskScenarioLabel: { type: String, default: '' },
|
||||||
|
selectedOnlineStateLabel: { type: String, default: '' },
|
||||||
|
selectedEnabledStateLabel: { type: String, default: '' },
|
||||||
|
showRiskScenarioFilter: { type: Boolean, default: false },
|
||||||
|
showOwnerFilter: { type: Boolean, default: false },
|
||||||
|
showRiskLevelFilter: { type: Boolean, default: false },
|
||||||
|
showStatusFilter: { type: Boolean, default: false },
|
||||||
|
showOnlineFilter: { type: Boolean, default: false },
|
||||||
|
showEnabledFilter: { type: Boolean, default: false },
|
||||||
|
domainOptions: { type: Array, default: () => [] },
|
||||||
|
ownerOptions: { type: Array, default: () => [] },
|
||||||
|
riskLevelOptions: { type: Array, default: () => [] },
|
||||||
|
statusOptions: { type: Array, default: () => [] },
|
||||||
|
riskScenarioOptions: { type: Array, default: () => [] },
|
||||||
|
onlineStateOptions: { type: Array, default: () => [] },
|
||||||
|
enabledStateOptions: { type: Array, default: () => [] },
|
||||||
|
activeFilterPopover: { type: String, default: '' },
|
||||||
|
activeFilterTokens: { type: Array, default: () => [] },
|
||||||
|
canCreateRiskRule: { type: Boolean, default: false }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits([
|
||||||
|
'update:activeType',
|
||||||
|
'update:keyword',
|
||||||
|
'toggle-filter-popover',
|
||||||
|
'close-filter-popover',
|
||||||
|
'select-filter',
|
||||||
|
'reset-filters',
|
||||||
|
'create-risk-rule',
|
||||||
|
'empty-action',
|
||||||
|
'open-asset-detail'
|
||||||
|
])
|
||||||
|
|
||||||
|
function selectFilter(type, value) {
|
||||||
|
emit('select-filter', type, value)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view.css"></style>
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view-part2.css"></style>
|
||||||
173
web/src/components/audit/AuditJsonRiskRuleDetail.vue
Normal file
173
web/src/components/audit/AuditJsonRiskRuleDetail.vue
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
<template>
|
||||||
|
<section class="json-risk-editor-shell panel">
|
||||||
|
<header class="json-risk-editor-head asset-detail-topbar list-toolbar">
|
||||||
|
<div class="json-risk-editor-title asset-detail-topbar-main filter-set">
|
||||||
|
<div class="json-risk-head-copy">
|
||||||
|
<div class="json-risk-head-title-row">
|
||||||
|
<h2>{{ selectedSkill.name }}</h2>
|
||||||
|
</div>
|
||||||
|
<p class="json-risk-head-subtitle">
|
||||||
|
{{ selectedSkill.riskRuleSubtitle || '平台通用风险规则' }}
|
||||||
|
</p>
|
||||||
|
<div class="json-risk-head-meta">
|
||||||
|
<span v-if="selectedSkill.riskCategory">适用场景:{{ selectedSkill.riskCategory }}</span>
|
||||||
|
<span>业务域:{{ selectedSkill.category || '-' }}</span>
|
||||||
|
<span>最近更新:{{ selectedSkill.updatedAt || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="json-risk-score-ring"
|
||||||
|
:class="selectedSkill.riskRuleScoreLevel || selectedSkill.riskRuleSeverity"
|
||||||
|
>
|
||||||
|
<strong>{{ selectedSkill.riskRuleScore ?? '--' }}</strong>
|
||||||
|
<span>风险分</span>
|
||||||
|
<em>{{ selectedSkill.riskRuleScoreLabel || selectedSkill.riskRuleSeverityLabel }}</em>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="selectedSkill.riskRuleGenerationFailed"
|
||||||
|
class="json-risk-generation-failure"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-alert-circle-outline"></i>
|
||||||
|
<div>
|
||||||
|
<h3>风险规则生成失败</h3>
|
||||||
|
<p>这条规则没有生成出可执行的 JSON 模板和流程图。管理员可以删除后重新创建。</p>
|
||||||
|
<small v-if="selectedSkill.riskRuleGenerationError">
|
||||||
|
失败原因:{{ selectedSkill.riskRuleGenerationError }}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="json-risk-editor-body">
|
||||||
|
<section class="json-risk-main-stage">
|
||||||
|
<article class="detail-card panel json-risk-summary-card">
|
||||||
|
<div class="card-head">
|
||||||
|
<div>
|
||||||
|
<h3>基本信息</h3>
|
||||||
|
<p>这条规则的业务域、风险等级、创建时间、上线状态和最近操作。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="json-risk-meta-grid">
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">业务域</span>
|
||||||
|
<span class="json-risk-meta-value">{{ selectedSkill.category || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">适用场景</span>
|
||||||
|
<span class="json-risk-meta-value">{{ selectedSkill.riskCategory || selectedSkill.scope || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">业务环节</span>
|
||||||
|
<span class="json-risk-meta-value">{{ selectedSkill.businessStageLabel || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">风险等级</span>
|
||||||
|
<span class="json-risk-meta-value">
|
||||||
|
<span class="json-risk-meta-badge" :class="selectedSkill.riskRuleSeverity">
|
||||||
|
{{ selectedSkill.riskRuleSeverityLabel || '-' }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">是否上线</span>
|
||||||
|
<span class="json-risk-meta-value">
|
||||||
|
<span class="json-risk-meta-badge" :class="selectedSkill.isOnlineValue ? 'test-passed' : 'test-pending'">
|
||||||
|
{{ selectedSkill.isOnlineLabel || '待上线' }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">测试状态</span>
|
||||||
|
<span class="json-risk-meta-value">
|
||||||
|
<span class="json-risk-meta-badge" :class="riskRuleTestPassed ? 'test-passed' : 'test-pending'">
|
||||||
|
{{ riskRuleTestPassed ? '已确认通过' : '待测试确认' }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">创建者</span>
|
||||||
|
<span class="json-risk-meta-value">{{ selectedSkill.creator || selectedSkill.publisher || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">创建时间</span>
|
||||||
|
<span class="json-risk-meta-value">
|
||||||
|
{{ selectedSkill.riskRuleCreatedAt || selectedSkill.updatedAt }}
|
||||||
|
<span v-if="selectedSkill.riskRuleAgeLabel" class="meta-value-hint">
|
||||||
|
({{ selectedSkill.riskRuleAgeLabel }})
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">上线时间</span>
|
||||||
|
<span class="json-risk-meta-value">{{ selectedSkill.publishedAt || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="json-risk-meta-item">
|
||||||
|
<span class="json-risk-meta-label">最后操作</span>
|
||||||
|
<span class="json-risk-meta-value">{{ selectedSkill.lastOperationLabel || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="json-risk-meta-item full-width">
|
||||||
|
<span class="json-risk-meta-label">使用字段</span>
|
||||||
|
<span class="json-risk-meta-value">{{ selectedSkill.riskRuleFieldSummary || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article
|
||||||
|
v-if="selectedSkill.riskRuleBusinessDescription"
|
||||||
|
class="detail-card panel json-risk-description-card"
|
||||||
|
>
|
||||||
|
<div class="card-head">
|
||||||
|
<div>
|
||||||
|
<h3>业务说明</h3>
|
||||||
|
<p>面向规则制定者和审核人的自然语言说明。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="json-risk-description-text">{{ selectedSkill.riskRuleBusinessDescription }}</p>
|
||||||
|
<p
|
||||||
|
v-if="selectedSkill.riskRuleSourceRef"
|
||||||
|
class="json-risk-description-source"
|
||||||
|
>
|
||||||
|
来源:{{ selectedSkill.riskRuleSourceRef }}
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="detail-card panel json-risk-flow-card">
|
||||||
|
<div class="card-head">
|
||||||
|
<div>
|
||||||
|
<h3>判断流程</h3>
|
||||||
|
<p>规则从业务单据开始,读取字段证据后按判断依据决定是否进入复核。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<RiskRuleFlowDiagram
|
||||||
|
:svg="selectedSkill.riskRuleFlowDiagramSvg"
|
||||||
|
:flow="selectedSkill.riskRuleFlow"
|
||||||
|
:fields="selectedSkill.riskRuleFields"
|
||||||
|
:severity="selectedSkill.riskRuleSeverity"
|
||||||
|
:severity-label="selectedSkill.riskRuleSeverityLabel"
|
||||||
|
/>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import RiskRuleFlowDiagram from '../shared/RiskRuleFlowDiagram.vue'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'AuditJsonRiskRuleDetail'
|
||||||
|
})
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
selectedSkill: { type: Object, required: true },
|
||||||
|
riskRuleTestPassed: { type: Boolean, default: false }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view.css"></style>
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view-part2.css"></style>
|
||||||
60
web/src/components/audit/AuditPickerFilter.vue
Normal file
60
web/src/components/audit/AuditPickerFilter.vue
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<div class="picker-filter" :class="{ open: activeFilterPopover === id }">
|
||||||
|
<button
|
||||||
|
class="picker-trigger"
|
||||||
|
type="button"
|
||||||
|
:aria-expanded="activeFilterPopover === id"
|
||||||
|
aria-haspopup="dialog"
|
||||||
|
@click="emit('toggle', id)"
|
||||||
|
>
|
||||||
|
<span class="picker-label">{{ label }}</span>
|
||||||
|
<i class="mdi mdi-chevron-down"></i>
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
v-if="activeFilterPopover === id"
|
||||||
|
class="picker-popover"
|
||||||
|
role="dialog"
|
||||||
|
:aria-label="title"
|
||||||
|
>
|
||||||
|
<header>
|
||||||
|
<strong>{{ title }}</strong>
|
||||||
|
<button type="button" :aria-label="closeLabel" @click="emit('close')">
|
||||||
|
<i class="mdi mdi-close"></i>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
<div class="picker-option-list">
|
||||||
|
<button
|
||||||
|
v-for="option in options"
|
||||||
|
:key="option.value || `all-${id}`"
|
||||||
|
type="button"
|
||||||
|
class="picker-option"
|
||||||
|
:class="{ active: selectedValue === option.value }"
|
||||||
|
@click="emit('select', option.value)"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineOptions({
|
||||||
|
name: 'AuditPickerFilter'
|
||||||
|
})
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
id: { type: String, required: true },
|
||||||
|
title: { type: String, required: true },
|
||||||
|
closeLabel: { type: String, required: true },
|
||||||
|
activeFilterPopover: { type: String, default: '' },
|
||||||
|
label: { type: String, default: '' },
|
||||||
|
options: { type: Array, default: () => [] },
|
||||||
|
selectedValue: { type: [String, Number, Boolean], default: '' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['toggle', 'close', 'select'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view.css"></style>
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view-part2.css"></style>
|
||||||
293
web/src/components/audit/AuditRuleDialogs.vue
Normal file
293
web/src/components/audit/AuditRuleDialogs.vue
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
<template>
|
||||||
|
<ConfirmDialog
|
||||||
|
:open="riskRuleCreateOpen"
|
||||||
|
badge="自然语言规则"
|
||||||
|
badge-tone="info"
|
||||||
|
title="新建风险规则"
|
||||||
|
description="默认创建费用类风险规则。选择业务环节和费用领域后填写规则标题与自然语言描述,系统会根据评分模型自动计算风险分数和等级。"
|
||||||
|
cancel-text="取消"
|
||||||
|
confirm-text="开始生成"
|
||||||
|
busy-text="生成中..."
|
||||||
|
confirm-tone="primary"
|
||||||
|
confirm-icon="mdi mdi-auto-fix"
|
||||||
|
:busy="riskRuleCreateBusy"
|
||||||
|
:close-on-mask="!riskRuleCreateBusy"
|
||||||
|
@close="emit('close-risk-rule-create')"
|
||||||
|
@confirm="emit('submit-risk-rule-create')"
|
||||||
|
>
|
||||||
|
<div class="risk-rule-create-form">
|
||||||
|
<label>
|
||||||
|
<span>业务环节</span>
|
||||||
|
<EnterpriseSelect
|
||||||
|
v-model="riskRuleCreateForm.business_stage"
|
||||||
|
:options="riskRuleBusinessStageOptions"
|
||||||
|
:disabled="riskRuleCreateBusy"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>费用领域</span>
|
||||||
|
<EnterpriseSelect
|
||||||
|
v-model="riskRuleCreateForm.expense_category"
|
||||||
|
:options="riskRuleExpenseCategoryOptions"
|
||||||
|
:disabled="riskRuleCreateBusy"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>是否上传附件</span>
|
||||||
|
<EnterpriseSelect
|
||||||
|
v-model="riskRuleCreateForm.requires_attachment"
|
||||||
|
:options="riskRuleAttachmentOptions"
|
||||||
|
:disabled="riskRuleCreateBusy"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label class="span-2">
|
||||||
|
<span>规则标题</span>
|
||||||
|
<input
|
||||||
|
v-model="riskRuleCreateForm.rule_title"
|
||||||
|
:disabled="riskRuleCreateBusy"
|
||||||
|
maxlength="80"
|
||||||
|
placeholder="例如:差旅目的地与票据城市一致性校验"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label class="span-2">
|
||||||
|
<span>自然语言规则</span>
|
||||||
|
<textarea
|
||||||
|
v-model="riskRuleCreateForm.natural_language"
|
||||||
|
:disabled="riskRuleCreateBusy"
|
||||||
|
placeholder="例如:住宿城市必须出现在本次差旅行程城市中,否则提示高风险并要求补充说明。"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
<RiskRuleTestDialog
|
||||||
|
:open="riskRuleTestOpen"
|
||||||
|
:rule="selectedSkill"
|
||||||
|
@close="emit('close-risk-rule-test')"
|
||||||
|
@report-saved="emit('report-saved', $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
:open="riskRuleDeleteOpen"
|
||||||
|
badge="删除规则"
|
||||||
|
badge-tone="danger"
|
||||||
|
title="删除未发布风险规则"
|
||||||
|
description="该操作会删除规则草稿、版本记录和关联 JSON 文件。只有从未发布过的规则允许删除。"
|
||||||
|
cancel-text="取消"
|
||||||
|
confirm-text="确认删除"
|
||||||
|
busy-text="删除中..."
|
||||||
|
confirm-tone="danger"
|
||||||
|
confirm-icon="mdi mdi-delete-outline"
|
||||||
|
:busy="actionState === 'delete-risk-rule'"
|
||||||
|
@close="emit('close-delete-risk-rule')"
|
||||||
|
@confirm="emit('delete-selected-risk-rule')"
|
||||||
|
>
|
||||||
|
<div class="risk-rule-action-confirm">
|
||||||
|
<span>规则名称</span>
|
||||||
|
<strong>{{ selectedSkill?.name }}</strong>
|
||||||
|
</div>
|
||||||
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
:open="riskRuleReturnOpen"
|
||||||
|
badge="回退规则"
|
||||||
|
badge-tone="warning"
|
||||||
|
title="回退风险规则"
|
||||||
|
description="回退后规则会回到草稿状态,编写人需要根据原因重新调整并测试。"
|
||||||
|
cancel-text="取消"
|
||||||
|
confirm-text="确认回退"
|
||||||
|
busy-text="回退中..."
|
||||||
|
confirm-tone="warning"
|
||||||
|
confirm-icon="mdi mdi-keyboard-return"
|
||||||
|
:busy="actionState === 'return-risk-rule'"
|
||||||
|
@close="emit('close-return-risk-rule')"
|
||||||
|
@confirm="emit('return-selected-risk-rule')"
|
||||||
|
>
|
||||||
|
<label class="risk-rule-action-note">
|
||||||
|
<span>回退原因</span>
|
||||||
|
<textarea
|
||||||
|
v-model="returnNoteModel"
|
||||||
|
rows="4"
|
||||||
|
:disabled="actionState === 'return-risk-rule'"
|
||||||
|
placeholder="请说明需要编写人调整的规则问题"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
:open="riskRulePublishOpen"
|
||||||
|
badge="发布上线"
|
||||||
|
badge-tone="info"
|
||||||
|
title="发布风险规则"
|
||||||
|
description="发布后该规则会进入真实业务风险扫描,只加载正式上线规则。"
|
||||||
|
cancel-text="取消"
|
||||||
|
confirm-text="确认发布"
|
||||||
|
busy-text="发布中..."
|
||||||
|
confirm-tone="primary"
|
||||||
|
confirm-icon="mdi mdi-rocket-launch-outline"
|
||||||
|
:busy="actionState === 'publish-risk-rule'"
|
||||||
|
@close="emit('close-publish-risk-rule')"
|
||||||
|
@confirm="emit('publish-selected-risk-rule')"
|
||||||
|
>
|
||||||
|
<div class="risk-rule-action-confirm">
|
||||||
|
<span>测试状态</span>
|
||||||
|
<strong>{{ riskRuleTestPassed ? '已确认通过' : '未确认通过' }}</strong>
|
||||||
|
</div>
|
||||||
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
:open="Boolean(versionSwitchTarget)"
|
||||||
|
badge="切换版本"
|
||||||
|
badge-tone="info"
|
||||||
|
title="切换规则版本"
|
||||||
|
description="切换后编辑器只会替换当前展示内容,不会直接回滚后端当前版本。"
|
||||||
|
cancel-text="取消"
|
||||||
|
confirm-text="确认切换"
|
||||||
|
busy-text="切换中..."
|
||||||
|
confirm-tone="primary"
|
||||||
|
confirm-icon="mdi mdi-swap-horizontal"
|
||||||
|
@close="emit('cancel-version-switch')"
|
||||||
|
@confirm="emit('confirm-version-switch')"
|
||||||
|
>
|
||||||
|
<div class="version-modal-summary">
|
||||||
|
<div>
|
||||||
|
<span>当前展示版本</span>
|
||||||
|
<strong>{{ selectedSkill?.displayVersion }}</strong>
|
||||||
|
</div>
|
||||||
|
<i class="mdi mdi-arrow-right"></i>
|
||||||
|
<div>
|
||||||
|
<span>目标版本</span>
|
||||||
|
<strong>{{ versionSwitchTarget?.version }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="versionSwitchTarget" class="version-modal-note">
|
||||||
|
<strong>{{ versionSwitchTarget.note }}</strong>
|
||||||
|
<span>{{ versionSwitchTarget.time }}</span>
|
||||||
|
</div>
|
||||||
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
:open="reviewSubmitOpen"
|
||||||
|
badge="提交审核"
|
||||||
|
badge-tone="info"
|
||||||
|
title="提交规则版本审核"
|
||||||
|
description="请先确认本次送审采用的版本号,并选择负责审核的高级管理员。若填写新的版本号,系统会将当前工作稿固化为该版本后再送审。"
|
||||||
|
cancel-text="取消"
|
||||||
|
confirm-text="确认提交"
|
||||||
|
busy-text="提交中..."
|
||||||
|
confirm-tone="primary"
|
||||||
|
confirm-icon="mdi mdi-send-outline"
|
||||||
|
:busy="actionState === 'review-pending'"
|
||||||
|
@close="emit('close-submit-review')"
|
||||||
|
@confirm="emit('submit-selected-rule-for-review')"
|
||||||
|
>
|
||||||
|
<div class="review-submit-form">
|
||||||
|
<label>
|
||||||
|
<span>送审版本号</span>
|
||||||
|
<input
|
||||||
|
v-model="reviewSubmitVersionModel"
|
||||||
|
type="text"
|
||||||
|
placeholder="例如:v1.1.0"
|
||||||
|
:disabled="actionState === 'review-pending'"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>审核人</span>
|
||||||
|
<EnterpriseSelect
|
||||||
|
v-model="reviewSubmitReviewerModel"
|
||||||
|
:options="reviewSubmitReviewerOptions"
|
||||||
|
:placeholder="reviewSubmitReviewerLoading ? '加载审核人中...' : '请选择高级管理员'"
|
||||||
|
:disabled="reviewSubmitReviewerLoading || actionState === 'review-pending'"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<p
|
||||||
|
v-if="!reviewSubmitReviewerLoading && !hasReviewSubmitReviewers"
|
||||||
|
class="review-submit-hint"
|
||||||
|
>
|
||||||
|
当前没有可选的高级管理员,请先在员工管理中配置具备管理员角色的员工。
|
||||||
|
</p>
|
||||||
|
<div v-if="selectedSkillUsesJsonRisk" class="review-submit-test-state">
|
||||||
|
<span>测试确认</span>
|
||||||
|
<strong :class="{ passed: riskRuleTestPassed }">
|
||||||
|
{{ riskRuleTestPassed ? '当前版本已通过测试确认' : '当前版本尚未确认测试通过' }}
|
||||||
|
</strong>
|
||||||
|
<p>只有保存测试报告的风险规则,才能提交给高级财务人员审核。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ConfirmDialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import ConfirmDialog from '../shared/ConfirmDialog.vue'
|
||||||
|
import EnterpriseSelect from '../shared/EnterpriseSelect.vue'
|
||||||
|
import RiskRuleTestDialog from '../shared/RiskRuleTestDialog.vue'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'AuditRuleDialogs'
|
||||||
|
})
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
selectedSkill: { type: Object, default: null },
|
||||||
|
versionSwitchTarget: { type: Object, default: null },
|
||||||
|
actionState: { type: String, default: '' },
|
||||||
|
riskRuleCreateOpen: { type: Boolean, default: false },
|
||||||
|
riskRuleCreateBusy: { type: Boolean, default: false },
|
||||||
|
riskRuleCreateForm: { type: Object, required: true },
|
||||||
|
riskRuleBusinessStageOptions: { type: Array, default: () => [] },
|
||||||
|
riskRuleExpenseCategoryOptions: { type: Array, default: () => [] },
|
||||||
|
riskRuleAttachmentOptions: { type: Array, default: () => [] },
|
||||||
|
riskRuleTestOpen: { type: Boolean, default: false },
|
||||||
|
riskRuleDeleteOpen: { type: Boolean, default: false },
|
||||||
|
riskRuleReturnOpen: { type: Boolean, default: false },
|
||||||
|
riskRulePublishOpen: { type: Boolean, default: false },
|
||||||
|
riskRuleReturnNote: { type: String, default: '' },
|
||||||
|
riskRuleTestPassed: { type: Boolean, default: false },
|
||||||
|
reviewSubmitOpen: { type: Boolean, default: false },
|
||||||
|
reviewSubmitVersion: { type: String, default: '' },
|
||||||
|
reviewSubmitReviewer: { type: String, default: '' },
|
||||||
|
reviewSubmitReviewerLoading: { type: Boolean, default: false },
|
||||||
|
reviewSubmitReviewerOptions: { type: Array, default: () => [] },
|
||||||
|
hasReviewSubmitReviewers: { type: Boolean, default: false },
|
||||||
|
selectedSkillUsesJsonRisk: { type: Boolean, default: false }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits([
|
||||||
|
'update:riskRuleReturnNote',
|
||||||
|
'update:reviewSubmitVersion',
|
||||||
|
'update:reviewSubmitReviewer',
|
||||||
|
'close-risk-rule-create',
|
||||||
|
'submit-risk-rule-create',
|
||||||
|
'close-risk-rule-test',
|
||||||
|
'report-saved',
|
||||||
|
'close-delete-risk-rule',
|
||||||
|
'delete-selected-risk-rule',
|
||||||
|
'close-return-risk-rule',
|
||||||
|
'return-selected-risk-rule',
|
||||||
|
'close-publish-risk-rule',
|
||||||
|
'publish-selected-risk-rule',
|
||||||
|
'cancel-version-switch',
|
||||||
|
'confirm-version-switch',
|
||||||
|
'close-submit-review',
|
||||||
|
'submit-selected-rule-for-review'
|
||||||
|
])
|
||||||
|
|
||||||
|
const returnNoteModel = computed({
|
||||||
|
get: () => props.riskRuleReturnNote,
|
||||||
|
set: (value) => emit('update:riskRuleReturnNote', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const reviewSubmitVersionModel = computed({
|
||||||
|
get: () => props.reviewSubmitVersion,
|
||||||
|
set: (value) => emit('update:reviewSubmitVersion', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const reviewSubmitReviewerModel = computed({
|
||||||
|
get: () => props.reviewSubmitReviewer,
|
||||||
|
set: (value) => emit('update:reviewSubmitReviewer', value)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view.css"></style>
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view-part2.css"></style>
|
||||||
112
web/src/components/audit/AuditSpreadsheetChangeDrawer.vue
Normal file
112
web/src/components/audit/AuditSpreadsheetChangeDrawer.vue
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<template>
|
||||||
|
<Transition name="drawer-fade">
|
||||||
|
<div v-if="open" class="rule-drawer-backdrop" @click.self="emit('close')">
|
||||||
|
<aside class="rule-drawer compare-drawer change-detail-drawer">
|
||||||
|
<header class="rule-drawer-head">
|
||||||
|
<div>
|
||||||
|
<span>最近修改</span>
|
||||||
|
<h3>修改详情</h3>
|
||||||
|
</div>
|
||||||
|
<button type="button" @click="emit('close')">
|
||||||
|
<i class="mdi mdi-close"></i>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div v-if="record" class="compare-content change-detail-content">
|
||||||
|
<section class="change-detail-meta">
|
||||||
|
<article>
|
||||||
|
<span>修改人</span>
|
||||||
|
<strong>{{ record.actor }}</strong>
|
||||||
|
</article>
|
||||||
|
<article>
|
||||||
|
<span>修改时间</span>
|
||||||
|
<strong>{{ record.time }}</strong>
|
||||||
|
</article>
|
||||||
|
<article>
|
||||||
|
<span>修改工作表</span>
|
||||||
|
<strong>{{ record.changed_sheet_count }}</strong>
|
||||||
|
</article>
|
||||||
|
<article>
|
||||||
|
<span>变更单元格</span>
|
||||||
|
<strong>{{ record.changed_cell_count }}</strong>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="compare-panel">
|
||||||
|
<header>
|
||||||
|
<strong>本次修改摘要</strong>
|
||||||
|
</header>
|
||||||
|
<p>{{ record.summary }}</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="compare-panel">
|
||||||
|
<header>
|
||||||
|
<strong>工作表变化</strong>
|
||||||
|
</header>
|
||||||
|
<div v-if="sheetRows.length" class="compare-sheet-list">
|
||||||
|
<span
|
||||||
|
v-for="item in sheetRows"
|
||||||
|
:key="`${item.sheet_name}-${item.change_type}`"
|
||||||
|
:class="item.meta.tone"
|
||||||
|
>
|
||||||
|
{{ item.sheet_name }} · {{ item.meta.label }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p v-else>本次没有工作表级变化。</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="compare-panel compare-cell-panel">
|
||||||
|
<header>
|
||||||
|
<strong>单元格差异</strong>
|
||||||
|
<small>最多展示前 500 条</small>
|
||||||
|
</header>
|
||||||
|
<div v-if="cellRows.length" class="compare-table-wrap">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>工作表</th>
|
||||||
|
<th>位置</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>旧值</th>
|
||||||
|
<th>新值</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="item in cellRows"
|
||||||
|
:key="`${item.sheet_name}-${item.cell}`"
|
||||||
|
>
|
||||||
|
<td>{{ item.sheet_name }}</td>
|
||||||
|
<td>{{ item.cell }}</td>
|
||||||
|
<td><b :class="item.meta.tone">{{ item.meta.label }}</b></td>
|
||||||
|
<td>{{ item.before_value ?? '-' }}</td>
|
||||||
|
<td>{{ item.after_value ?? '-' }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p v-else>本次没有发现单元格级差异。</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineOptions({
|
||||||
|
name: 'AuditSpreadsheetChangeDrawer'
|
||||||
|
})
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
open: { type: Boolean, default: false },
|
||||||
|
record: { type: Object, default: null },
|
||||||
|
sheetRows: { type: Array, default: () => [] },
|
||||||
|
cellRows: { type: Array, default: () => [] }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['close'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view.css"></style>
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view-part2.css"></style>
|
||||||
159
web/src/components/audit/AuditSpreadsheetRuleDetail.vue
Normal file
159
web/src/components/audit/AuditSpreadsheetRuleDetail.vue
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<template>
|
||||||
|
<section class="spreadsheet-editor-shell panel">
|
||||||
|
<header class="spreadsheet-editor-head asset-detail-topbar list-toolbar">
|
||||||
|
<div class="spreadsheet-editor-title asset-detail-topbar-main filter-set">
|
||||||
|
<div class="skill-badge" :class="selectedSkill.badgeTone">{{ selectedSkill.typeLabel }}</div>
|
||||||
|
<div>
|
||||||
|
<h2>{{ selectedSkill.name }}</h2>
|
||||||
|
<p>{{ selectedSkill.summary || '当前资产尚未补充说明。' }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="spreadsheet-editor-actions asset-detail-topbar-meta toolbar-actions">
|
||||||
|
<span class="spreadsheet-mode-pill">
|
||||||
|
{{ selectedSpreadsheetModeLabel }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<input
|
||||||
|
ref="fileInput"
|
||||||
|
class="spreadsheet-upload-input"
|
||||||
|
type="file"
|
||||||
|
accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||||
|
@change="emit('file-change', $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="spreadsheet-editor-body">
|
||||||
|
<section class="spreadsheet-main-stage">
|
||||||
|
<div class="spreadsheet-editor-meta">
|
||||||
|
<span><strong>文件</strong>{{ selectedSpreadsheetFileName }}</span>
|
||||||
|
<span><strong>负责人</strong>{{ selectedSkill.owner }}</span>
|
||||||
|
<span><strong>最近更新</strong>{{ selectedSkill.updatedAt }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="spreadsheet-workbench">
|
||||||
|
<div
|
||||||
|
:key="spreadsheetOnlyOfficeHostId"
|
||||||
|
:id="spreadsheetOnlyOfficeHostId"
|
||||||
|
class="rule-spreadsheet-host"
|
||||||
|
:class="{ hidden: !spreadsheetOnlyOfficeReady && !spreadsheetOnlyOfficeError }"
|
||||||
|
></div>
|
||||||
|
<TableLoadingState
|
||||||
|
v-if="spreadsheetOnlyOfficeLoading"
|
||||||
|
class="rule-spreadsheet-state"
|
||||||
|
variant="overlay"
|
||||||
|
tone="sky"
|
||||||
|
message="正在加载 Excel 规则表"
|
||||||
|
icon="mdi mdi-table-large"
|
||||||
|
:show-skeleton="false"
|
||||||
|
/>
|
||||||
|
<div v-else-if="spreadsheetOnlyOfficeError" class="rule-spreadsheet-state error">
|
||||||
|
<i class="mdi mdi-alert-circle-outline"></i>
|
||||||
|
<span>{{ spreadsheetOnlyOfficeError }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="spreadsheet-editor-foot">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
canEditSpreadsheetInline
|
||||||
|
? '可直接在线编辑;保存后,右侧会自动记录本次修改内容。'
|
||||||
|
: '当前为只读预览模式。'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
<span>右侧仅展示最近 30 次修改操作。</span>
|
||||||
|
</footer>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<aside class="spreadsheet-change-center">
|
||||||
|
<header class="change-center-head">
|
||||||
|
<div>
|
||||||
|
<h3>最近修改</h3>
|
||||||
|
<p>展示最近 30 次保存后的具体改动。</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="change-center-section change-history-section">
|
||||||
|
<div v-if="selectedSpreadsheetChangeRecords.length" class="change-center-list">
|
||||||
|
<button
|
||||||
|
v-for="item in selectedSpreadsheetChangeRecords"
|
||||||
|
:key="`spreadsheet-change-${item.id || item.changed_at}-${item.actor}`"
|
||||||
|
type="button"
|
||||||
|
class="change-center-item change-record-item"
|
||||||
|
@click="emit('open-spreadsheet-change-detail', item)"
|
||||||
|
>
|
||||||
|
<div class="change-record-head">
|
||||||
|
<div>
|
||||||
|
<strong>{{ item.actor }}</strong>
|
||||||
|
<span>{{ item.time }}</span>
|
||||||
|
</div>
|
||||||
|
<b>{{ item.changeCountLabel }}</b>
|
||||||
|
</div>
|
||||||
|
<p>{{ item.summary }}</p>
|
||||||
|
<small v-if="item.sheetPreview.length">
|
||||||
|
涉及工作表:{{ item.sheetPreview.join('、') }}
|
||||||
|
<template v-if="item.remainingSheetCount"> 等 {{ item.changedSheetNames.length }} 个</template>
|
||||||
|
</small>
|
||||||
|
<div v-if="item.previewChanges.length" class="change-record-preview">
|
||||||
|
<span
|
||||||
|
v-for="change in item.previewChanges"
|
||||||
|
:key="`${change.sheet_name}-${change.cell}`"
|
||||||
|
>
|
||||||
|
{{ change.sheet_name }}!{{ change.cell }}:
|
||||||
|
{{ change.before_value ?? '-' }} → {{ change.after_value ?? '-' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<small v-if="item.remainingChangeCount" class="change-record-more">
|
||||||
|
另有 {{ item.remainingChangeCount }} 处改动
|
||||||
|
</small>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p v-else class="change-flow-empty">暂无修改记录</p>
|
||||||
|
</section>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import TableLoadingState from '../shared/TableLoadingState.vue'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'AuditSpreadsheetRuleDetail'
|
||||||
|
})
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
selectedSkill: { type: Object, required: true },
|
||||||
|
selectedSpreadsheetModeLabel: { type: String, default: '' },
|
||||||
|
selectedSpreadsheetFileName: { type: String, default: '' },
|
||||||
|
selectedSpreadsheetChangeRecords: { type: Array, default: () => [] },
|
||||||
|
spreadsheetOnlyOfficeHostId: { type: String, required: true },
|
||||||
|
spreadsheetOnlyOfficeReady: { type: Boolean, default: false },
|
||||||
|
spreadsheetOnlyOfficeError: { type: String, default: '' },
|
||||||
|
spreadsheetOnlyOfficeLoading: { type: Boolean, default: false },
|
||||||
|
canEditSpreadsheetInline: { type: Boolean, default: false }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['file-change', 'open-spreadsheet-change-detail'])
|
||||||
|
const fileInput = ref(null)
|
||||||
|
|
||||||
|
function click() {
|
||||||
|
fileInput.value?.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
if (fileInput.value) {
|
||||||
|
fileInput.value.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
click,
|
||||||
|
reset
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view.css"></style>
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view-part2.css"></style>
|
||||||
71
web/src/components/audit/AuditVersionTimelineDrawer.vue
Normal file
71
web/src/components/audit/AuditVersionTimelineDrawer.vue
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<Transition name="drawer-fade">
|
||||||
|
<div v-if="open" class="rule-drawer-backdrop" @click.self="emit('close')">
|
||||||
|
<aside class="rule-drawer timeline-drawer">
|
||||||
|
<header class="rule-drawer-head">
|
||||||
|
<div>
|
||||||
|
<span>修改记录</span>
|
||||||
|
<h3>文档操作记录</h3>
|
||||||
|
</div>
|
||||||
|
<button type="button" @click="emit('close')">
|
||||||
|
<i class="mdi mdi-close"></i>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<TableLoadingState
|
||||||
|
v-if="loading"
|
||||||
|
class="rule-drawer-state"
|
||||||
|
variant="drawer"
|
||||||
|
message="正在加载操作记录"
|
||||||
|
icon="mdi mdi-history"
|
||||||
|
:show-skeleton="false"
|
||||||
|
/>
|
||||||
|
<div v-else-if="error" class="rule-drawer-state error">
|
||||||
|
<i class="mdi mdi-alert-circle-outline"></i>
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="items.length" class="rule-timeline-list">
|
||||||
|
<article
|
||||||
|
v-for="item in items"
|
||||||
|
:key="`${item.event_type}-${item.version}-${item.event_time}`"
|
||||||
|
class="rule-timeline-item"
|
||||||
|
>
|
||||||
|
<i :class="[item.meta.icon, item.meta.tone]"></i>
|
||||||
|
<div>
|
||||||
|
<header>
|
||||||
|
<strong>{{ item.meta.label }}</strong>
|
||||||
|
<span>{{ item.timeLabel }}</span>
|
||||||
|
</header>
|
||||||
|
<p>{{ item.description || item.note || '暂无补充说明' }}</p>
|
||||||
|
<small>操作人:{{ item.actor }}</small>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<div v-else class="rule-drawer-state">
|
||||||
|
<i class="mdi mdi-history"></i>
|
||||||
|
<span>暂无操作记录</span>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import TableLoadingState from '../shared/TableLoadingState.vue'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'AuditVersionTimelineDrawer'
|
||||||
|
})
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
open: { type: Boolean, default: false },
|
||||||
|
loading: { type: Boolean, default: false },
|
||||||
|
error: { type: String, default: '' },
|
||||||
|
items: { type: Array, default: () => [] }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['close'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view.css"></style>
|
||||||
|
<style scoped src="../../assets/styles/views/audit-view-part2.css"></style>
|
||||||
@@ -347,8 +347,8 @@ const todoItems = [
|
|||||||
suggestion: '补充客户单位、客户人数、我方陪同人员',
|
suggestion: '补充客户单位、客户人数、我方陪同人员',
|
||||||
action: '去补充',
|
action: '去补充',
|
||||||
iconKey: 'hospitality',
|
iconKey: 'hospitality',
|
||||||
color: '#0d9668',
|
color: 'var(--theme-primary-active)',
|
||||||
accent: '#6ee7b7'
|
accent: 'var(--theme-primary-soft-strong)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '差旅报销单待提交',
|
title: '差旅报销单待提交',
|
||||||
@@ -356,8 +356,8 @@ const todoItems = [
|
|||||||
suggestion: '补齐出发交通,可直接生成报销单',
|
suggestion: '补齐出发交通,可直接生成报销单',
|
||||||
action: '继续填写',
|
action: '继续填写',
|
||||||
iconKey: 'travelDraft',
|
iconKey: 'travelDraft',
|
||||||
color: '#15803d',
|
color: 'var(--success-hover)',
|
||||||
accent: '#86efac'
|
accent: 'var(--success-line)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '有 5 张票据未关联报销单',
|
title: '有 5 张票据未关联报销单',
|
||||||
@@ -365,8 +365,8 @@ const todoItems = [
|
|||||||
suggestion: '其中 3 张疑似交通费,可合并生成交通报销',
|
suggestion: '其中 3 张疑似交通费,可合并生成交通报销',
|
||||||
action: '去整理',
|
action: '去整理',
|
||||||
iconKey: 'receipts',
|
iconKey: 'receipts',
|
||||||
color: '#2563eb',
|
color: 'var(--chart-blue)',
|
||||||
accent: '#93c5fd'
|
accent: 'var(--theme-primary-soft-strong)'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -381,8 +381,8 @@ const progressItems = [
|
|||||||
status: '主管审批中',
|
status: '主管审批中',
|
||||||
tone: 'success',
|
tone: 'success',
|
||||||
iconKey: 'flight',
|
iconKey: 'flight',
|
||||||
color: '#0d9668',
|
color: 'var(--theme-primary-active)',
|
||||||
accent: '#6ee7b7'
|
accent: 'var(--theme-primary-soft-strong)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'transport',
|
id: 'transport',
|
||||||
@@ -392,8 +392,8 @@ const progressItems = [
|
|||||||
status: '财务复核中',
|
status: '财务复核中',
|
||||||
tone: 'info',
|
tone: 'info',
|
||||||
iconKey: 'transport',
|
iconKey: 'transport',
|
||||||
color: '#2563eb',
|
color: 'var(--chart-blue)',
|
||||||
accent: '#93c5fd'
|
accent: 'var(--theme-primary-soft-strong)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'office',
|
id: 'office',
|
||||||
@@ -403,8 +403,8 @@ const progressItems = [
|
|||||||
status: '已到账',
|
status: '已到账',
|
||||||
tone: 'mint',
|
tone: 'mint',
|
||||||
iconKey: 'procurement',
|
iconKey: 'procurement',
|
||||||
color: '#059669',
|
color: 'var(--success)',
|
||||||
accent: '#a7f3d0'
|
accent: 'var(--success-line)'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -453,710 +453,4 @@ watch(
|
|||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped src="../../assets/styles/components/personal-workbench.css"></style>
|
||||||
.workbench {
|
|
||||||
min-width: 0;
|
|
||||||
display: grid;
|
|
||||||
gap: 16px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-hero {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 228px minmax(0, 1fr);
|
|
||||||
gap: 18px;
|
|
||||||
padding: 20px 24px 20px 18px;
|
|
||||||
border: 1px solid rgba(16, 185, 129, 0.12);
|
|
||||||
background:
|
|
||||||
radial-gradient(circle at top left, rgba(16, 185, 129, 0.12), transparent 34%),
|
|
||||||
radial-gradient(circle at right 20%, rgba(59, 130, 246, 0.07), transparent 28%),
|
|
||||||
linear-gradient(135deg, #f7fffb 0%, #ffffff 48%, #f5fbff 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-hero::before,
|
|
||||||
.assistant-hero::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: rgba(16, 185, 129, 0.06);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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(220, 252, 231, 0.84) 58%, rgba(220, 252, 231, 0) 100%);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-visual::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: 52px;
|
|
||||||
bottom: 18px;
|
|
||||||
width: 132px;
|
|
||||||
height: 18px;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: rgba(16, 185, 129, 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(236, 253, 245, 0.9) 58%, rgba(236, 253, 245, 0) 100%);
|
|
||||||
box-shadow: 0 24px 48px rgba(16, 185, 129, 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;
|
|
||||||
display: grid;
|
|
||||||
gap: 10px;
|
|
||||||
align-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-copy h3 {
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 26px;
|
|
||||||
line-height: 1.25;
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-copy p {
|
|
||||||
max-width: 760px;
|
|
||||||
color: #5b6b83;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-input {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 48px;
|
|
||||||
padding: 4px 14px;
|
|
||||||
border: 1px solid rgba(148, 163, 184, 0.28);
|
|
||||||
border-radius: 12px;
|
|
||||||
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-input textarea {
|
|
||||||
min-width: 0;
|
|
||||||
flex: 1;
|
|
||||||
height: 22px;
|
|
||||||
min-height: 22px;
|
|
||||||
max-height: 22px;
|
|
||||||
resize: none;
|
|
||||||
border: 0;
|
|
||||||
padding: 1px 0;
|
|
||||||
background: transparent;
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 22px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-input textarea::placeholder {
|
|
||||||
color: #94a3b8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-input 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: 10px;
|
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
|
||||||
color: #fff;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 800;
|
|
||||||
white-space: nowrap;
|
|
||||||
box-shadow: 0 10px 22px rgba(16, 185, 129, 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 {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-file-strip {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-file-note,
|
|
||||||
.assistant-file-chip {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 30px;
|
|
||||||
padding: 0 12px;
|
|
||||||
border-radius: 999px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-file-note {
|
|
||||||
background: rgba(16, 185, 129, 0.1);
|
|
||||||
color: #047857;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assistant-file-chip {
|
|
||||||
max-width: 220px;
|
|
||||||
overflow: hidden;
|
|
||||||
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;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ghost-action {
|
|
||||||
height: 40px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 0 16px;
|
|
||||||
border: 1px solid rgba(15, 118, 110, 0.18);
|
|
||||||
border-radius: 10px;
|
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.94), rgba(244, 250, 247, 0.88));
|
|
||||||
color: #0f766e;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 700;
|
|
||||||
box-shadow:
|
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.9),
|
|
||||||
0 6px 14px rgba(15, 118, 110, 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ghost-action .mdi {
|
|
||||||
color: #10b981;
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondary-action {
|
|
||||||
height: 40px;
|
|
||||||
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: 10px;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
.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 {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
gap: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-panel,
|
|
||||||
.policy-panel {
|
|
||||||
padding: 20px 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-head {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 12px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-head h3 {
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 17px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-with-badge {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-badge {
|
|
||||||
min-width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-action {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
color: #10b981;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-body {
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.todo-row,
|
|
||||||
.progress-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 56px minmax(0, 1fr) auto;
|
|
||||||
gap: 14px;
|
|
||||||
align-items: center;
|
|
||||||
padding: 14px 0;
|
|
||||||
border-top: 1px solid #edf2f7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.todo-row:first-child,
|
|
||||||
.progress-row:first-child {
|
|
||||||
padding-top: 4px;
|
|
||||||
border-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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: #ecfdf5;
|
|
||||||
color: #059669;
|
|
||||||
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(16, 185, 129, 0.36);
|
|
||||||
border-radius: 10px;
|
|
||||||
color: #10b981;
|
|
||||||
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: #eafaf2;
|
|
||||||
color: #16935f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-status.info,
|
|
||||||
.policy-status.info {
|
|
||||||
background: #eff6ff;
|
|
||||||
color: #3b82f6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-status.mint {
|
|
||||||
background: #edfdf5;
|
|
||||||
color: #10b981;
|
|
||||||
}
|
|
||||||
|
|
||||||
.policy-table {
|
|
||||||
border: 1px solid #e7edf5;
|
|
||||||
border-radius: 12px;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.policy-row strong {
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.policy-row span {
|
|
||||||
color: #64748b;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.policy-title-cell,
|
|
||||||
.policy-summary-cell {
|
|
||||||
justify-self: stretch;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.policy-date-cell {
|
|
||||||
justify-self: center;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1320px) {
|
|
||||||
.assistant-copy h3 {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.policy-row {
|
|
||||||
grid-template-columns: 1.8fr 1.8fr 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -28,12 +28,22 @@ import {
|
|||||||
BarElement,
|
BarElement,
|
||||||
Tooltip
|
Tooltip
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
|
import { resolveCssColor, useThemeColors } from '../../composables/useThemeColors.js'
|
||||||
|
|
||||||
ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip)
|
ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip)
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
items: { type: Array, required: true }
|
items: { type: Array, required: true }
|
||||||
})
|
})
|
||||||
|
const themeColors = useThemeColors()
|
||||||
|
const resolvedItems = computed(() => {
|
||||||
|
const fallback = themeColors.value.chartPrimary
|
||||||
|
|
||||||
|
return props.items.map((item) => ({
|
||||||
|
...item,
|
||||||
|
resolvedColor: resolveCssColor(item.color, fallback)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
const medalClass = (idx) => {
|
const medalClass = (idx) => {
|
||||||
if (idx === 0) return 'gold'
|
if (idx === 0) return 'gold'
|
||||||
@@ -56,10 +66,10 @@ const formatValue = (value) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const chartData = computed(() => ({
|
const chartData = computed(() => ({
|
||||||
labels: props.items.map((i) => i.name || i.shortName),
|
labels: resolvedItems.value.map((i) => i.name || i.shortName),
|
||||||
datasets: [{
|
datasets: [{
|
||||||
data: props.items.map((i) => i.value || i.amount),
|
data: resolvedItems.value.map((i) => i.value || i.amount),
|
||||||
backgroundColor: props.items.map((i) => i.color),
|
backgroundColor: resolvedItems.value.map((i) => i.resolvedColor),
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
borderSkipped: false,
|
borderSkipped: false,
|
||||||
barPercentage: 0.7,
|
barPercentage: 0.7,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
Tooltip
|
Tooltip
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
||||||
|
import { useThemeColors } from '../../composables/useThemeColors.js'
|
||||||
|
|
||||||
ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip, Legend)
|
ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip, Legend)
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ const progress = useAnimationProgress([
|
|||||||
() => props.occupied,
|
() => props.occupied,
|
||||||
() => props.available
|
() => props.available
|
||||||
], 1000)
|
], 1000)
|
||||||
|
const themeColors = useThemeColors()
|
||||||
|
|
||||||
const currency = (value) =>
|
const currency = (value) =>
|
||||||
Number(value || 0).toLocaleString('zh-CN', {
|
Number(value || 0).toLocaleString('zh-CN', {
|
||||||
@@ -77,7 +79,7 @@ const chartData = computed(() => ({
|
|||||||
{
|
{
|
||||||
label: '已使用',
|
label: '已使用',
|
||||||
data: scaleSeries(usedPercent.value),
|
data: scaleSeries(usedPercent.value),
|
||||||
backgroundColor: '#13a66b',
|
backgroundColor: themeColors.value.chartPrimary,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
borderSkipped: false,
|
borderSkipped: false,
|
||||||
stack: 'budgetUsage',
|
stack: 'budgetUsage',
|
||||||
@@ -86,7 +88,7 @@ const chartData = computed(() => ({
|
|||||||
{
|
{
|
||||||
label: '已占用',
|
label: '已占用',
|
||||||
data: scaleSeries(occupiedPercent.value),
|
data: scaleSeries(occupiedPercent.value),
|
||||||
backgroundColor: '#f59e0b',
|
backgroundColor: themeColors.value.warning,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
borderSkipped: false,
|
borderSkipped: false,
|
||||||
stack: 'budgetUsage',
|
stack: 'budgetUsage',
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="donut-legend">
|
<div class="donut-legend">
|
||||||
<div v-for="item in items" :key="item.name" class="legend-row">
|
<div v-for="item in items" :key="item.name" class="legend-row">
|
||||||
<i :style="{ background: item.color }"></i>
|
<i :style="{ background: item.resolvedColor }"></i>
|
||||||
<span class="legend-name">{{ item.name }}</span>
|
<span class="legend-name">{{ item.name }}</span>
|
||||||
<span class="legend-val">{{ item.display }}</span>
|
<span class="legend-val">{{ item.display }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
Legend
|
Legend
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
||||||
|
import { resolveCssColor, useThemeColors } from '../../composables/useThemeColors.js'
|
||||||
|
|
||||||
ChartJS.register(ArcElement, Tooltip, Legend)
|
ChartJS.register(ArcElement, Tooltip, Legend)
|
||||||
|
|
||||||
@@ -37,12 +38,21 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const progress = useAnimationProgress([() => props.items], 1150)
|
const progress = useAnimationProgress([() => props.items], 1150)
|
||||||
|
const themeColors = useThemeColors()
|
||||||
|
const resolvedItems = computed(() => {
|
||||||
|
const fallback = themeColors.value.chartPrimary
|
||||||
|
|
||||||
|
return props.items.map((item) => ({
|
||||||
|
...item,
|
||||||
|
resolvedColor: resolveCssColor(item.color, fallback)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
const chartData = computed(() => ({
|
const chartData = computed(() => ({
|
||||||
labels: props.items.map((i) => i.name),
|
labels: resolvedItems.value.map((i) => i.name),
|
||||||
datasets: [{
|
datasets: [{
|
||||||
data: props.items.map((i) => Math.max(Number((i.value * progress.value).toFixed(1)), 0.001)),
|
data: resolvedItems.value.map((i) => Math.max(Number((i.value * progress.value).toFixed(1)), 0.001)),
|
||||||
backgroundColor: props.items.map((i) => i.color),
|
backgroundColor: resolvedItems.value.map((i) => i.resolvedColor),
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
cutout: '68%',
|
cutout: '68%',
|
||||||
spacing: 3,
|
spacing: 3,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
Tooltip
|
Tooltip
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
||||||
|
import { useThemeColors } from '../../composables/useThemeColors.js'
|
||||||
|
|
||||||
ChartJS.register(ArcElement, Tooltip)
|
ChartJS.register(ArcElement, Tooltip)
|
||||||
|
|
||||||
@@ -46,12 +47,13 @@ const props = defineProps({
|
|||||||
const ratioValue = computed(() => Number(props.ratio))
|
const ratioValue = computed(() => Number(props.ratio))
|
||||||
const progress = useAnimationProgress([() => props.ratio], 1150)
|
const progress = useAnimationProgress([() => props.ratio], 1150)
|
||||||
const animatedRatio = computed(() => Number((ratioValue.value * progress.value).toFixed(0)))
|
const animatedRatio = computed(() => Number((ratioValue.value * progress.value).toFixed(0)))
|
||||||
|
const themeColors = useThemeColors()
|
||||||
|
|
||||||
const chartData = computed(() => ({
|
const chartData = computed(() => ({
|
||||||
labels: ['已执行', '剩余'],
|
labels: ['已执行', '剩余'],
|
||||||
datasets: [{
|
datasets: [{
|
||||||
data: [animatedRatio.value, 100 - animatedRatio.value],
|
data: [animatedRatio.value, 100 - animatedRatio.value],
|
||||||
backgroundColor: ['#10b981', '#e2e8f0'],
|
backgroundColor: [themeColors.value.chartPrimary, '#e2e8f0'],
|
||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
}]
|
}]
|
||||||
}))
|
}))
|
||||||
@@ -101,7 +103,7 @@ const chartOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gauge-center strong {
|
.gauge-center strong {
|
||||||
color: #10b981;
|
color: var(--chart-primary);
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="log-trend-chart">
|
<div class="log-trend-chart">
|
||||||
<div class="chart-legend">
|
<div class="chart-legend">
|
||||||
<span><i style="background:#10b981"></i>日志总量</span>
|
<span><i :style="{ background: chartColors.primary }"></i>日志总量</span>
|
||||||
<span><i style="background:#ef4444"></i>失败数</span>
|
<span><i :style="{ background: chartColors.danger }"></i>失败数</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-body">
|
<div class="chart-body">
|
||||||
<Bar :data="chartData" :options="chartOptions" />
|
<Bar :data="chartData" :options="chartOptions" />
|
||||||
@@ -24,6 +24,7 @@ import {
|
|||||||
Legend
|
Legend
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
||||||
|
import { useThemeColors } from '../../composables/useThemeColors.js'
|
||||||
|
|
||||||
ChartJS.register(CategoryScale, LinearScale, BarElement, PointElement, LineElement, Tooltip, Legend)
|
ChartJS.register(CategoryScale, LinearScale, BarElement, PointElement, LineElement, Tooltip, Legend)
|
||||||
|
|
||||||
@@ -38,6 +39,11 @@ const progress = useAnimationProgress([
|
|||||||
() => props.totals,
|
() => props.totals,
|
||||||
() => props.failures
|
() => props.failures
|
||||||
], 1000)
|
], 1000)
|
||||||
|
const themeColors = useThemeColors()
|
||||||
|
const chartColors = computed(() => ({
|
||||||
|
primary: themeColors.value.chartPrimary,
|
||||||
|
danger: themeColors.value.chartDanger
|
||||||
|
}))
|
||||||
|
|
||||||
const scaleSeries = (series) =>
|
const scaleSeries = (series) =>
|
||||||
series.map((value) => Math.round(Number(value || 0) * progress.value))
|
series.map((value) => Math.round(Number(value || 0) * progress.value))
|
||||||
@@ -50,7 +56,7 @@ const chartData = computed(() => ({
|
|||||||
{
|
{
|
||||||
label: '日志总量',
|
label: '日志总量',
|
||||||
data: scaleSeries(props.totals),
|
data: scaleSeries(props.totals),
|
||||||
backgroundColor: '#10b981',
|
backgroundColor: chartColors.value.primary,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
barPercentage: 0.58,
|
barPercentage: 0.58,
|
||||||
categoryPercentage: 0.56,
|
categoryPercentage: 0.56,
|
||||||
@@ -59,11 +65,11 @@ const chartData = computed(() => ({
|
|||||||
{
|
{
|
||||||
label: '失败数',
|
label: '失败数',
|
||||||
data: scaleSeries(props.failures),
|
data: scaleSeries(props.failures),
|
||||||
borderColor: '#ef4444',
|
borderColor: chartColors.value.danger,
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
pointBackgroundColor: '#ffffff',
|
pointBackgroundColor: '#ffffff',
|
||||||
pointBorderColor: '#ef4444',
|
pointBorderColor: chartColors.value.danger,
|
||||||
pointBorderWidth: 2,
|
pointBorderWidth: 2,
|
||||||
pointRadius: 3,
|
pointRadius: 3,
|
||||||
pointHoverRadius: 5,
|
pointHoverRadius: 5,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="trend-chart">
|
<div class="trend-chart">
|
||||||
<div class="chart-legend">
|
<div class="chart-legend">
|
||||||
<span><i style="background:#10b981"></i>申请量(单)</span>
|
<span><i :style="{ background: chartColors.primary }"></i>申请量(单)</span>
|
||||||
<span><i style="background:#3b82f6"></i>审批完成量(单)</span>
|
<span><i :style="{ background: chartColors.blue }"></i>审批完成量(单)</span>
|
||||||
<span><i style="background:#8b5cf6"></i>平均审批时长(小时)</span>
|
<span><i :style="{ background: chartColors.purple }"></i>平均审批时长(小时)</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-body">
|
<div class="chart-body">
|
||||||
<Bar :data="chartData" :options="chartOptions" />
|
<Bar :data="chartData" :options="chartOptions" />
|
||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
Legend
|
Legend
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
import { useAnimationProgress } from '../../composables/useAnimationProgress.js'
|
||||||
|
import { useThemeColors } from '../../composables/useThemeColors.js'
|
||||||
|
|
||||||
ChartJS.register(CategoryScale, LinearScale, BarElement, PointElement, LineElement, Filler, Tooltip, Legend)
|
ChartJS.register(CategoryScale, LinearScale, BarElement, PointElement, LineElement, Filler, Tooltip, Legend)
|
||||||
|
|
||||||
@@ -42,6 +43,12 @@ const progress = useAnimationProgress([
|
|||||||
() => props.approved,
|
() => props.approved,
|
||||||
() => props.avgHours
|
() => props.avgHours
|
||||||
], 1200)
|
], 1200)
|
||||||
|
const themeColors = useThemeColors()
|
||||||
|
const chartColors = computed(() => ({
|
||||||
|
primary: themeColors.value.chartPrimary,
|
||||||
|
blue: themeColors.value.chartBlue,
|
||||||
|
purple: themeColors.value.chartPurple
|
||||||
|
}))
|
||||||
|
|
||||||
const scaleSeries = (series, decimals = 0) =>
|
const scaleSeries = (series, decimals = 0) =>
|
||||||
series.map((value) => Number((Number(value) * progress.value).toFixed(decimals)))
|
series.map((value) => Number((Number(value) * progress.value).toFixed(decimals)))
|
||||||
@@ -52,7 +59,7 @@ const chartData = computed(() => ({
|
|||||||
{
|
{
|
||||||
label: '申请量(单)',
|
label: '申请量(单)',
|
||||||
data: scaleSeries(props.applications),
|
data: scaleSeries(props.applications),
|
||||||
backgroundColor: '#10b981',
|
backgroundColor: chartColors.value.primary,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
barPercentage: 0.6,
|
barPercentage: 0.6,
|
||||||
categoryPercentage: 0.5,
|
categoryPercentage: 0.5,
|
||||||
@@ -61,7 +68,7 @@ const chartData = computed(() => ({
|
|||||||
{
|
{
|
||||||
label: '审批完成量(单)',
|
label: '审批完成量(单)',
|
||||||
data: scaleSeries(props.approved),
|
data: scaleSeries(props.approved),
|
||||||
backgroundColor: '#3b82f6',
|
backgroundColor: chartColors.value.blue,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
barPercentage: 0.6,
|
barPercentage: 0.6,
|
||||||
categoryPercentage: 0.5,
|
categoryPercentage: 0.5,
|
||||||
@@ -70,11 +77,11 @@ const chartData = computed(() => ({
|
|||||||
{
|
{
|
||||||
label: '平均审批时长(小时)',
|
label: '平均审批时长(小时)',
|
||||||
data: scaleSeries(props.avgHours, 1),
|
data: scaleSeries(props.avgHours, 1),
|
||||||
borderColor: '#8b5cf6',
|
borderColor: chartColors.value.purple,
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
pointBackgroundColor: '#ffffff',
|
pointBackgroundColor: '#ffffff',
|
||||||
pointBorderColor: '#8b5cf6',
|
pointBorderColor: chartColors.value.purple,
|
||||||
pointBorderWidth: 2,
|
pointBorderWidth: 2,
|
||||||
pointRadius: 3,
|
pointRadius: 3,
|
||||||
pointHoverRadius: 5,
|
pointHoverRadius: 5,
|
||||||
|
|||||||
@@ -1,41 +1,57 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="doc-filters" aria-label="单据筛选">
|
<section class="doc-filters" aria-label="单据筛选">
|
||||||
<div class="filter-item">
|
<label class="filter-item">
|
||||||
<span class="filter-label">申请月份</span>
|
<span class="filter-label">申请月份</span>
|
||||||
<Dropdown v-model="docFilters.month" :options="docMonths" placeholder="选择月份" appendTo="body" class="filter-dropdown">
|
<EnterpriseSelect
|
||||||
<template #option="{ option }">
|
v-model="docFilters.month"
|
||||||
{{ formatMonth(option) }}
|
:options="monthOptions"
|
||||||
</template>
|
placeholder="选择月份"
|
||||||
<template #value="{ value }">
|
/>
|
||||||
{{ formatMonth(value) }}
|
</label>
|
||||||
</template>
|
|
||||||
</Dropdown>
|
<label class="filter-item">
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<span class="filter-label">申请类型</span>
|
<span class="filter-label">申请类型</span>
|
||||||
<Dropdown v-model="docFilters.type" :options="docTypes" placeholder="选择类型" appendTo="body" class="filter-dropdown" />
|
<EnterpriseSelect
|
||||||
</div>
|
v-model="docFilters.type"
|
||||||
<div class="filter-item">
|
:options="docTypes"
|
||||||
|
placeholder="选择类型"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="filter-item">
|
||||||
<span class="filter-label">单据状态</span>
|
<span class="filter-label">单据状态</span>
|
||||||
<Dropdown v-model="docFilters.status" :options="docStatuses" placeholder="选择状态" appendTo="body" class="filter-dropdown" />
|
<EnterpriseSelect
|
||||||
</div>
|
v-model="docFilters.status"
|
||||||
|
:options="docStatuses"
|
||||||
|
placeholder="选择状态"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import Dropdown from 'primevue/dropdown'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
defineProps({
|
import EnterpriseSelect from '../shared/EnterpriseSelect.vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
docFilters: { type: Object, required: true },
|
docFilters: { type: Object, required: true },
|
||||||
docMonths: { type: Array, required: true },
|
docMonths: { type: Array, required: true },
|
||||||
docTypes: { type: Array, required: true },
|
docTypes: { type: Array, required: true },
|
||||||
docStatuses: { type: Array, required: true }
|
docStatuses: { type: Array, required: true }
|
||||||
})
|
})
|
||||||
|
|
||||||
function formatMonth(m) {
|
const monthOptions = computed(() =>
|
||||||
if (!m) return ''
|
props.docMonths.map((month) => ({
|
||||||
const [y, mm] = m.split('-')
|
label: formatMonth(month),
|
||||||
return `${y}年${parseInt(mm)}月`
|
value: month
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
function formatMonth(month) {
|
||||||
|
if (!month) return ''
|
||||||
|
const [year, rawMonth] = String(month).split('-')
|
||||||
|
return `${year}年${Number.parseInt(rawMonth, 10)}月`
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -43,12 +59,27 @@ function formatMonth(m) {
|
|||||||
.doc-filters {
|
.doc-filters {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(180px, 1fr));
|
grid-template-columns: repeat(3, minmax(180px, 1fr));
|
||||||
gap: 14px;
|
gap: 12px;
|
||||||
padding: 16px 28px;
|
padding: 14px 24px;
|
||||||
border-bottom: 1px solid var(--line);
|
border-bottom: 1px solid var(--line);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
}
|
}
|
||||||
.filter-item { display: grid; gap: 6px; }
|
|
||||||
.filter-label { color: var(--muted); font-size: 12px; font-weight: 700; }
|
.filter-item {
|
||||||
.filter-dropdown { width: 100%; }
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-label {
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px) {
|
||||||
|
.doc-filters {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
padding-inline: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,35 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="filters" :class="{ compact }" aria-label="筛选条件">
|
<section class="filters" :class="{ compact }" aria-label="筛选条件">
|
||||||
<template v-if="!compact">
|
<template v-if="!compact">
|
||||||
<label>
|
<label class="filter-field">
|
||||||
<span>法人主体</span>
|
<span>法人主体</span>
|
||||||
<select v-model="filters.entity">
|
<EnterpriseSelect
|
||||||
<option>全部主体</option>
|
v-model="filters.entity"
|
||||||
<option>Northstar China Ltd.</option>
|
:options="entityOptions"
|
||||||
<option>Northstar Singapore Pte.</option>
|
placeholder="选择主体"
|
||||||
<option>Northstar US Inc.</option>
|
/>
|
||||||
</select>
|
</label>
|
||||||
</label>
|
|
||||||
<label>
|
<label class="filter-field">
|
||||||
<span>费用类型</span>
|
<span>费用类型</span>
|
||||||
<select v-model="filters.category">
|
<EnterpriseSelect
|
||||||
<option>全部费用</option>
|
v-model="filters.category"
|
||||||
<option>机票</option>
|
:options="categoryOptions"
|
||||||
<option>酒店</option>
|
placeholder="选择费用"
|
||||||
<option>火车/用车</option>
|
/>
|
||||||
<option>餐补及杂费</option>
|
</label>
|
||||||
</select>
|
|
||||||
</label>
|
<label class="filter-field">
|
||||||
<label>
|
<span>风险等级</span>
|
||||||
<span>风险等级</span>
|
<EnterpriseSelect
|
||||||
<select v-model="filters.risk">
|
v-model="filters.risk"
|
||||||
<option>全部风险</option>
|
:options="riskOptions"
|
||||||
<option>高风险</option>
|
placeholder="选择风险"
|
||||||
<option>需解释</option>
|
/>
|
||||||
<option>低风险</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="segmented-wrap" :class="{ compact }">
|
<div class="segmented-wrap" :class="{ compact }">
|
||||||
<span v-if="!compact">时间范围</span>
|
<span v-if="!compact">时间范围</span>
|
||||||
<div class="segmented" role="tablist" aria-label="处理视图">
|
<div class="segmented" role="tablist" aria-label="处理视图">
|
||||||
@@ -48,6 +47,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import EnterpriseSelect from '../shared/EnterpriseSelect.vue'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
filters: { type: Object, required: true },
|
filters: { type: Object, required: true },
|
||||||
ranges: { type: Array, required: true },
|
ranges: { type: Array, required: true },
|
||||||
@@ -56,13 +57,35 @@ defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:activeRange'])
|
const emit = defineEmits(['update:activeRange'])
|
||||||
|
|
||||||
|
const entityOptions = [
|
||||||
|
'全部主体',
|
||||||
|
'Northstar China Ltd.',
|
||||||
|
'Northstar Singapore Pte.',
|
||||||
|
'Northstar US Inc.'
|
||||||
|
]
|
||||||
|
|
||||||
|
const categoryOptions = [
|
||||||
|
'全部费用',
|
||||||
|
'机票',
|
||||||
|
'酒店',
|
||||||
|
'火车/用车',
|
||||||
|
'餐补及杂费'
|
||||||
|
]
|
||||||
|
|
||||||
|
const riskOptions = [
|
||||||
|
'全部风险',
|
||||||
|
'高风险',
|
||||||
|
'需解释',
|
||||||
|
'低风险'
|
||||||
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.filters {
|
.filters {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(160px, 1fr)) auto;
|
grid-template-columns: repeat(3, minmax(160px, 1fr)) auto;
|
||||||
gap: 14px;
|
gap: 12px;
|
||||||
padding: 0 16px 12px;
|
padding: 0 16px 12px;
|
||||||
border-bottom: 1px solid var(--line);
|
border-bottom: 1px solid var(--line);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
@@ -74,7 +97,7 @@ const emit = defineEmits(['update:activeRange'])
|
|||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filters label,
|
.filter-field,
|
||||||
.segmented-wrap {
|
.segmented-wrap {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
@@ -83,15 +106,6 @@ const emit = defineEmits(['update:activeRange'])
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filters select {
|
|
||||||
height: 40px;
|
|
||||||
padding: 0 12px;
|
|
||||||
border: 1px solid #cbd5e1;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: #fff;
|
|
||||||
color: var(--ink);
|
|
||||||
}
|
|
||||||
|
|
||||||
.segmented-wrap {
|
.segmented-wrap {
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
}
|
}
|
||||||
@@ -99,38 +113,40 @@ const emit = defineEmits(['update:activeRange'])
|
|||||||
.segmented {
|
.segmented {
|
||||||
align-self: end;
|
align-self: end;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: 0;
|
min-height: 36px;
|
||||||
min-height: 40px;
|
padding: 2px;
|
||||||
padding: 3px;
|
border: 1px solid #d8dee8;
|
||||||
border-radius: 10px;
|
border-radius: 4px;
|
||||||
background: #f1f5f9;
|
background: #f8fafc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.segmented button {
|
.segmented button {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 34px;
|
min-height: 30px;
|
||||||
padding: 0 20px;
|
padding: 0 16px;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 8px;
|
border-radius: 3px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition:
|
||||||
|
background 160ms var(--ease),
|
||||||
|
color 160ms var(--ease),
|
||||||
|
box-shadow 160ms var(--ease);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.segmented button:hover:not(.active) {
|
.segmented button:hover:not(.active) {
|
||||||
color: #334155;
|
color: #334155;
|
||||||
background: rgba(255, 255, 255, 0.5);
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.segmented button.active {
|
.segmented button.active {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #1e293b;
|
color: var(--primary-active);
|
||||||
font-weight: 600;
|
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 980px) {
|
@media (max-width: 980px) {
|
||||||
|
|||||||
@@ -244,514 +244,4 @@ onBeforeUnmount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped src="../../assets/styles/components/sidebar-rail.css"></style>
|
||||||
.rail {
|
|
||||||
--rail-motion-duration: 320ms;
|
|
||||||
--rail-motion-ease: cubic-bezier(0.22, 1, 0.36, 1);
|
|
||||||
--rail-fade-duration: 160ms;
|
|
||||||
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: var(--desktop-stage-height, 100dvh);
|
|
||||||
min-height: var(--desktop-stage-height, 100dvh);
|
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 251, 250, 0.96)), #fff;
|
|
||||||
border-right: 1px solid #dbe4ee;
|
|
||||||
box-shadow: 1px 0 0 rgba(15, 23, 42, 0.02);
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-brand {
|
|
||||||
position: relative;
|
|
||||||
min-height: 92px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 12px;
|
|
||||||
padding: 22px 16px 18px;
|
|
||||||
overflow: hidden;
|
|
||||||
transition:
|
|
||||||
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
gap var(--rail-motion-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-mark {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
color: #07936f;
|
|
||||||
border-radius: 6px;
|
|
||||||
overflow: hidden;
|
|
||||||
transition:
|
|
||||||
width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
height var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
margin var(--rail-motion-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-logo {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-mark svg {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
fill: currentColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-name {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-width: 0;
|
|
||||||
max-width: 124px;
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 800;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
transition:
|
|
||||||
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
opacity var(--rail-fade-duration) var(--rail-motion-ease),
|
|
||||||
transform var(--rail-fade-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapse-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 16px;
|
|
||||||
top: 31px;
|
|
||||||
z-index: 2;
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
display: inline-grid;
|
|
||||||
place-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid rgba(148, 163, 184, 0.22);
|
|
||||||
border-radius: 9px;
|
|
||||||
background: rgba(255, 255, 255, 0.86);
|
|
||||||
color: #64748b;
|
|
||||||
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.06);
|
|
||||||
transition:
|
|
||||||
top var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
right var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
transform var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
background 180ms var(--ease),
|
|
||||||
border-color 180ms var(--ease),
|
|
||||||
color 180ms var(--ease),
|
|
||||||
box-shadow 180ms var(--ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapse-btn:hover {
|
|
||||||
border-color: rgba(16, 185, 129, 0.28);
|
|
||||||
background: #ecfdf5;
|
|
||||||
color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapse-btn .mdi {
|
|
||||||
font-size: 18px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-nav {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 16px 20px;
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
flex: 1;
|
|
||||||
transition:
|
|
||||||
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
gap var(--rail-motion-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-btn {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 48px;
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
padding: 0 12px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: transparent;
|
|
||||||
color: #64748b;
|
|
||||||
text-align: left;
|
|
||||||
overflow: hidden;
|
|
||||||
transition:
|
|
||||||
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
gap var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
background 180ms var(--ease),
|
|
||||||
border-color 180ms var(--ease),
|
|
||||||
color 180ms var(--ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-btn:hover {
|
|
||||||
background: rgba(16, 185, 129, 0.07);
|
|
||||||
color: #0f9f78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-btn.active {
|
|
||||||
background: #ecfdf5;
|
|
||||||
border-color: rgba(16, 185, 129, 0.12);
|
|
||||||
color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-icon {
|
|
||||||
flex: 0 0 28px;
|
|
||||||
width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
border-radius: 7px;
|
|
||||||
color: currentColor;
|
|
||||||
transition:
|
|
||||||
flex-basis var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
height var(--rail-motion-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-btn :deep(svg) {
|
|
||||||
width: 19px;
|
|
||||||
height: 19px;
|
|
||||||
stroke: currentColor;
|
|
||||||
stroke-width: 2;
|
|
||||||
fill: none;
|
|
||||||
stroke-linecap: round;
|
|
||||||
stroke-linejoin: round;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-label {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
max-width: 128px;
|
|
||||||
color: currentColor;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 700;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
opacity: 1;
|
|
||||||
transition:
|
|
||||||
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
opacity var(--rail-fade-duration) var(--rail-motion-ease),
|
|
||||||
transform var(--rail-fade-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-badge {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
min-width: 34px;
|
|
||||||
height: 22px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0 8px;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: #ff5b67;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 800;
|
|
||||||
transition:
|
|
||||||
min-width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
opacity var(--rail-fade-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-unread-dot {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border: 2px solid #fff;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: #ef4444;
|
|
||||||
box-shadow: 0 6px 14px rgba(239, 68, 68, 0.26);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-user {
|
|
||||||
position: relative;
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 78px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 16px 20px 18px;
|
|
||||||
border-top: 1px solid #edf2f7;
|
|
||||||
transition: padding var(--rail-motion-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-summary {
|
|
||||||
position: relative;
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 42px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
padding: 4px;
|
|
||||||
color: #64748b;
|
|
||||||
border-radius: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition:
|
|
||||||
gap var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
padding var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
background 180ms var(--ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-user:hover .user-summary {
|
|
||||||
background: rgba(255, 255, 255, 0.72);
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-avatar {
|
|
||||||
flex: 0 0 36px;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
border: 2px solid #fff;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: linear-gradient(135deg, #0f9f78, #65d6b4);
|
|
||||||
box-shadow: 0 6px 14px rgba(15, 159, 120, 0.18);
|
|
||||||
color: #fff;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 800;
|
|
||||||
transition:
|
|
||||||
flex-basis var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
height var(--rail-motion-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-copy {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
max-width: 116px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
opacity: 1;
|
|
||||||
transition:
|
|
||||||
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
opacity var(--rail-fade-duration) var(--rail-motion-ease),
|
|
||||||
transform var(--rail-fade-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-copy strong {
|
|
||||||
color: #334155;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 750;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-copy span {
|
|
||||||
color: #64748b;
|
|
||||||
font-size: 12px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-summary .mdi {
|
|
||||||
flex: 0 0 18px;
|
|
||||||
font-size: 18px;
|
|
||||||
transition:
|
|
||||||
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
|
||||||
opacity var(--rail-fade-duration) var(--rail-motion-ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-menu {
|
|
||||||
position: absolute;
|
|
||||||
right: 20px;
|
|
||||||
bottom: calc(100% - 6px);
|
|
||||||
min-width: 132px;
|
|
||||||
padding: 8px;
|
|
||||||
border: 1px solid rgba(226, 232, 240, 0.96);
|
|
||||||
border-radius: 12px;
|
|
||||||
background: rgba(255, 255, 255, 0.98);
|
|
||||||
box-shadow: 0 16px 32px rgba(15, 23, 42, 0.1);
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(8px);
|
|
||||||
pointer-events: none;
|
|
||||||
transition: all 180ms var(--ease);
|
|
||||||
z-index: 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-user:hover .user-menu {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-menu-item {
|
|
||||||
width: 100%;
|
|
||||||
height: 38px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 0 12px;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 9px;
|
|
||||||
background: transparent;
|
|
||||||
color: #dc2626;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 700;
|
|
||||||
transition: all 180ms var(--ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================= */
|
|
||||||
/* COLLAPSED STATE */
|
|
||||||
/* ========================================= */
|
|
||||||
|
|
||||||
.rail-collapsed .rail-brand {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 8px;
|
|
||||||
min-height: 0;
|
|
||||||
padding: 24px 8px 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .brand-mark {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .brand-mark svg {
|
|
||||||
width: 34px;
|
|
||||||
height: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .brand-name {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px;
|
|
||||||
height: 1px;
|
|
||||||
max-width: 0;
|
|
||||||
margin: 0;
|
|
||||||
opacity: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0 0 0 0);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .rail-collapse-btn {
|
|
||||||
position: static;
|
|
||||||
top: auto;
|
|
||||||
right: auto;
|
|
||||||
align-self: center;
|
|
||||||
width: 36px;
|
|
||||||
height: 32px;
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .rail-nav {
|
|
||||||
gap: 10px;
|
|
||||||
padding: 12px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .nav-btn {
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0;
|
|
||||||
gap: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .nav-icon {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
flex: 0 0 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .nav-label {
|
|
||||||
max-width: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-6px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .nav-badge {
|
|
||||||
max-width: 0;
|
|
||||||
min-width: 0;
|
|
||||||
padding: 0;
|
|
||||||
opacity: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .nav-unread-dot {
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
right: 11px;
|
|
||||||
width: 9px;
|
|
||||||
height: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed {
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .rail-user {
|
|
||||||
position: relative;
|
|
||||||
z-index: 6;
|
|
||||||
padding: 14px 8px;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .user-summary {
|
|
||||||
justify-content: center;
|
|
||||||
padding: 4px;
|
|
||||||
gap: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-user-menu-floating {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 12000;
|
|
||||||
min-width: 132px;
|
|
||||||
padding: 8px;
|
|
||||||
border: 1px solid rgba(226, 232, 240, 0.96);
|
|
||||||
border-radius: 12px;
|
|
||||||
background: rgba(255, 255, 255, 0.98);
|
|
||||||
box-shadow: 0 16px 32px rgba(15, 23, 42, 0.14);
|
|
||||||
transform: translateY(-50%);
|
|
||||||
animation: railUserMenuIn 180ms var(--rail-motion-ease) both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-user-menu-floating .user-menu-item {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes railUserMenuIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-50%) translateX(-6px);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(-50%) translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rail-collapsed .user-copy,
|
|
||||||
.rail-collapsed .user-summary .mdi {
|
|
||||||
max-width: 0;
|
|
||||||
opacity: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
transform: translateX(-6px);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 980px) {
|
|
||||||
.rail {
|
|
||||||
position: relative;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
.rail *,
|
|
||||||
.rail *::before,
|
|
||||||
.rail *::after {
|
|
||||||
transition: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ const workbenchKpis = computed(() => {
|
|||||||
unit: '笔',
|
unit: '笔',
|
||||||
meta: '本月累计',
|
meta: '本月累计',
|
||||||
trend: monthlyCount > 0 ? 'up' : 'down',
|
trend: monthlyCount > 0 ? 'up' : 'down',
|
||||||
color: '#10b981'
|
color: 'var(--theme-primary)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '本月报销总金额',
|
label: '本月报销总金额',
|
||||||
@@ -299,10 +299,10 @@ const requestKpis = computed(() => {
|
|||||||
const completed = Number(summary.completed ?? 0)
|
const completed = Number(summary.completed ?? 0)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{ label: '全部单据', value: total, delta: '当前', trend: 'up', arrow: 'mdi mdi-minus', color: '#10b981' },
|
{ label: '全部单据', value: total, delta: '当前', trend: 'up', arrow: 'mdi mdi-minus', color: 'var(--theme-primary)' },
|
||||||
{ label: '草稿', value: draft, delta: '待提交', trend: draft > 0 ? 'down' : 'up', arrow: draft > 0 ? 'mdi mdi-arrow-down' : 'mdi mdi-minus', color: '#f59e0b' },
|
{ label: '草稿', value: draft, delta: '待提交', trend: draft > 0 ? 'down' : 'up', arrow: draft > 0 ? 'mdi mdi-arrow-down' : 'mdi mdi-minus', color: '#f59e0b' },
|
||||||
{ label: '审批中', value: inProgress, delta: '处理中', trend: inProgress > 0 ? 'up' : 'down', arrow: inProgress > 0 ? 'mdi mdi-arrow-up' : 'mdi mdi-minus', color: '#3b82f6' },
|
{ label: '审批中', value: inProgress, delta: '处理中', trend: inProgress > 0 ? 'up' : 'down', arrow: inProgress > 0 ? 'mdi mdi-arrow-up' : 'mdi mdi-minus', color: '#3b82f6' },
|
||||||
{ label: '已完成', value: completed, delta: '已归档', trend: 'up', arrow: 'mdi mdi-arrow-up' , color: '#10b981' }
|
{ label: '已完成', value: completed, delta: '已归档', trend: 'up', arrow: 'mdi mdi-arrow-up' , color: 'var(--success)' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -314,10 +314,10 @@ const documentKpis = computed(() => {
|
|||||||
const archived = Number(summary.archived ?? 0)
|
const archived = Number(summary.archived ?? 0)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{ label: '全部单据', value: total, delta: '当前', trend: 'up', arrow: 'mdi mdi-minus', color: '#10b981' },
|
{ label: '全部单据', value: total, delta: '当前', trend: 'up', arrow: 'mdi mdi-minus', color: 'var(--theme-primary)' },
|
||||||
{ label: '待提交', value: toSubmit, delta: '草稿待办', trend: toSubmit > 0 ? 'down' : 'up', arrow: toSubmit > 0 ? 'mdi mdi-arrow-down' : 'mdi mdi-minus', color: '#f59e0b' },
|
{ label: '待提交', value: toSubmit, delta: '草稿待办', trend: toSubmit > 0 ? 'down' : 'up', arrow: toSubmit > 0 ? 'mdi mdi-arrow-down' : 'mdi mdi-minus', color: '#f59e0b' },
|
||||||
{ label: '待我处理', value: toProcess, delta: '审批待办', trend: toProcess > 0 ? 'down' : 'up', arrow: toProcess > 0 ? 'mdi mdi-arrow-down' : 'mdi mdi-minus', color: '#3b82f6' },
|
{ label: '待我处理', value: toProcess, delta: '审批待办', trend: toProcess > 0 ? 'down' : 'up', arrow: toProcess > 0 ? 'mdi mdi-arrow-down' : 'mdi mdi-minus', color: '#3b82f6' },
|
||||||
{ label: '已归档', value: archived, delta: '归档入账', trend: 'up', arrow: 'mdi mdi-arrow-up', color: '#10b981' }
|
{ label: '已归档', value: archived, delta: '归档入账', trend: 'up', arrow: 'mdi mdi-arrow-up', color: 'var(--success)' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -329,25 +329,25 @@ const logsKpis = computed(() => {
|
|||||||
const failed = Number(summary.failed ?? 0)
|
const failed = Number(summary.failed ?? 0)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{ label: 'Hermes 总任务', value: total, unit: '条', meta: '当前', trend: 'up', color: '#10b981' },
|
{ label: 'Hermes 总任务', value: total, unit: '条', meta: '当前', trend: 'up', color: 'var(--theme-primary)' },
|
||||||
{ label: '运行中', value: running, unit: '条', meta: running > 0 ? '实时执行' : '暂无执行', trend: running > 0 ? 'up' : 'down', color: '#3b82f6' },
|
{ label: '运行中', value: running, unit: '条', meta: running > 0 ? '实时执行' : '暂无执行', trend: running > 0 ? 'up' : 'down', color: '#3b82f6' },
|
||||||
{ label: '已完成', value: completed, unit: '条', meta: total ? `占比 ${Math.round((completed / total) * 100)}%` : '等待数据', trend: 'up', color: '#10b981' },
|
{ label: '已完成', value: completed, unit: '条', meta: total ? `占比 ${Math.round((completed / total) * 100)}%` : '等待数据', trend: 'up', color: 'var(--success)' },
|
||||||
{ label: '失败数', value: failed, unit: '条', meta: failed > 0 ? '需要关注' : '运行正常', trend: failed > 0 ? 'down' : 'up', color: '#ef4444' }
|
{ label: '失败数', value: failed, unit: '条', meta: failed > 0 ? '需要关注' : '运行正常', trend: failed > 0 ? 'down' : 'up', color: '#ef4444' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
const chatKpis = [
|
const chatKpis = [
|
||||||
{ label: '今日已问数', value: 86, unit: '次', meta: '较昨日 +18', trend: 'up', color: '#10b981' },
|
{ label: '今日已问数', value: 86, unit: '次', meta: '较昨日 +18', trend: 'up', color: 'var(--theme-primary)' },
|
||||||
{ label: '已解决问题', value: 72, unit: '条', meta: '解决率 83.7%', trend: 'up', color: '#3b82f6' },
|
{ label: '已解决问题', value: 72, unit: '条', meta: '解决率 83.7%', trend: 'up', color: '#3b82f6' },
|
||||||
{ label: '知识命中率', value: '92.3', unit: '%', meta: '较昨日 +2.6%', trend: 'up', color: '#8b5cf6' },
|
{ label: '知识命中率', value: '92.3', unit: '%', meta: '较昨日 +2.6%', trend: 'up', color: '#8b5cf6' },
|
||||||
{ label: '平均响应时长', value: 2.1, unit: 's', meta: '较昨日 -0.3s', trend: 'down', color: '#f59e0b' }
|
{ label: '平均响应时长', value: 2.1, unit: 's', meta: '较昨日 -0.3s', trend: 'down', color: '#f59e0b' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const approvalKpis = [
|
const approvalKpis = [
|
||||||
{ label: '待审批单据', value: 12, unit: '单', meta: '较昨日 +3', trend: 'up', color: '#059669' },
|
{ label: '待审批单据', value: 12, unit: '单', meta: '较昨日 +3', trend: 'up', color: 'var(--theme-primary)' },
|
||||||
{ label: '高风险单据', value: 4, unit: '单', meta: '较昨日 +1', trend: 'up', color: '#ef4444' },
|
{ label: '高风险单据', value: 4, unit: '单', meta: '较昨日 +1', trend: 'up', color: '#ef4444' },
|
||||||
{ label: '即将超时', value: 3, unit: '单', meta: '30 分钟内', trend: 'down', color: '#f59e0b' },
|
{ label: '即将超时', value: 3, unit: '单', meta: '30 分钟内', trend: 'down', color: '#f59e0b' },
|
||||||
{ label: '今日已处理', value: 28, unit: '单', meta: '通过率 86%', trend: 'up', color: '#10b981' }
|
{ label: '今日已处理', value: 28, unit: '单', meta: '通过率 86%', trend: 'up', color: 'var(--success)' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const knowledgeKpis = computed(() => {
|
const knowledgeKpis = computed(() => {
|
||||||
@@ -360,7 +360,7 @@ const knowledgeKpis = computed(() => {
|
|||||||
value: String(totalDocuments),
|
value: String(totalDocuments),
|
||||||
meta: '',
|
meta: '',
|
||||||
trend: 'up',
|
trend: 'up',
|
||||||
color: '#10b981'
|
color: 'var(--theme-primary)'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@@ -381,7 +381,7 @@ const employeeKpis = computed(() => {
|
|||||||
unit: '人',
|
unit: '人',
|
||||||
meta: `覆盖 ${departments} 个部门`,
|
meta: `覆盖 ${departments} 个部门`,
|
||||||
trend: 'up',
|
trend: 'up',
|
||||||
color: '#10b981'
|
color: 'var(--theme-primary)'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '在职账号',
|
label: '在职账号',
|
||||||
@@ -499,438 +499,4 @@ function buildPresetRangeLabel(label) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped src="../../assets/styles/components/top-bar.css"></style>
|
||||||
.topbar {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 24px;
|
|
||||||
padding: 18px 24px 20px;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.topbar.chat-mode {
|
|
||||||
padding-bottom: 16px;
|
|
||||||
border-bottom: 1px solid #eef2f7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-group {
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.eyebrow {
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
padding: 3px 10px;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: linear-gradient(135deg, rgba(16, 185, 129, 0.10), rgba(59, 130, 246, 0.10));
|
|
||||||
color: #0d9668;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 800;
|
|
||||||
letter-spacing: 1.2px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.topbar h1 {
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 26px;
|
|
||||||
font-weight: 800;
|
|
||||||
letter-spacing: 0;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.topbar p {
|
|
||||||
margin-top: 6px;
|
|
||||||
max-width: 720px;
|
|
||||||
color: #64748b;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 14px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-combo {
|
|
||||||
position: relative;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-shell {
|
|
||||||
height: 42px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 3px;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-meta {
|
|
||||||
height: 34px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 0 12px;
|
|
||||||
border-right: 1px solid #e2e8f0;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 650;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-meta .mdi {
|
|
||||||
color: #10b981;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-tabs {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 2px;
|
|
||||||
padding-left: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-tabs button {
|
|
||||||
height: 34px;
|
|
||||||
min-width: 54px;
|
|
||||||
padding: 0 14px;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: transparent;
|
|
||||||
color: #64748b;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 700;
|
|
||||||
white-space: nowrap;
|
|
||||||
transition: background 160ms ease, color 160ms ease, box-shadow 160ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-tabs button:hover:not(.active) {
|
|
||||||
background: #f1f5f9;
|
|
||||||
color: #334155;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-tabs button.active {
|
|
||||||
background: #10b981;
|
|
||||||
color: #fff;
|
|
||||||
box-shadow: 0 6px 14px rgba(16, 185, 129, .18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-range-wrap {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-range-btn {
|
|
||||||
height: 42px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 0 13px;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #fff;
|
|
||||||
color: #334155;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 750;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-range-btn:hover,
|
|
||||||
.custom-range-btn.active {
|
|
||||||
border-color: rgba(16, 185, 129, .34);
|
|
||||||
background: #f6fffb;
|
|
||||||
color: #0f9f78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-popover {
|
|
||||||
position: absolute;
|
|
||||||
top: calc(100% + 10px);
|
|
||||||
right: 0;
|
|
||||||
width: 336px;
|
|
||||||
z-index: 40;
|
|
||||||
display: grid;
|
|
||||||
gap: 14px;
|
|
||||||
padding: 16px;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 12px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 18px 42px rgba(15, 23, 42, .16);
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-popover header,
|
|
||||||
.calendar-popover footer {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-popover header strong {
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-popover header button {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: transparent;
|
|
||||||
color: #64748b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-fields {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-fields label {
|
|
||||||
display: grid;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-fields span {
|
|
||||||
color: #64748b;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-fields input {
|
|
||||||
width: 100%;
|
|
||||||
height: 38px;
|
|
||||||
padding: 0 9px;
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
border-radius: 8px;
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ghost-btn,
|
|
||||||
.apply-btn {
|
|
||||||
height: 36px;
|
|
||||||
padding: 0 14px;
|
|
||||||
border-radius: 8px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 750;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ghost-btn {
|
|
||||||
border: 1px solid #d7e0ea;
|
|
||||||
background: #fff;
|
|
||||||
color: #334155;
|
|
||||||
}
|
|
||||||
|
|
||||||
.apply-btn {
|
|
||||||
border: 0;
|
|
||||||
background: #10b981;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.apply-btn:disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
background: #cbd5e1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kpi-chips {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-alert-strip {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 10px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-alert-pill {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
min-height: 32px;
|
|
||||||
padding: 0 12px;
|
|
||||||
border: 1px solid #fed7aa;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: #fff7ed;
|
|
||||||
color: #ea580c;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 800;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-alert-pill i {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-alert-pill.success {
|
|
||||||
border-color: #bbf7d0;
|
|
||||||
background: #f0fdf4;
|
|
||||||
color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-alert-pill.danger {
|
|
||||||
border-color: #fecaca;
|
|
||||||
background: #fff1f2;
|
|
||||||
color: #dc2626;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kpi-chip {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto auto;
|
|
||||||
grid-template-rows: auto auto;
|
|
||||||
gap: 2px 10px;
|
|
||||||
padding: 8px 16px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: linear-gradient(135deg, color-mix(in srgb, var(--chip-color) 8%, #fff), color-mix(in srgb, var(--chip-color) 3%, #f8fafc));
|
|
||||||
border: 1px solid color-mix(in srgb, var(--chip-color) 18%, #e2e8f0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.chip-value {
|
|
||||||
grid-row: 1 / 3;
|
|
||||||
align-self: center;
|
|
||||||
color: #0f172a;
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: 850;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chip-value small {
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chip-label {
|
|
||||||
color: #64748b;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chip-delta {
|
|
||||||
color: #94a3b8;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chip-delta.up { color: #059669; }
|
|
||||||
.chip-delta.down { color: #f59e0b; }
|
|
||||||
|
|
||||||
.topbar-spacer {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.create-top-btn {
|
|
||||||
height: 40px;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 0 18px;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: #059669;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 750;
|
|
||||||
box-shadow: 0 8px 18px rgba(5, 150, 105, 0.18);
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.create-top-btn:hover {
|
|
||||||
background: #047857;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1120px) {
|
|
||||||
.range-combo {
|
|
||||||
width: 100%;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 960px) {
|
|
||||||
.topbar {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-actions,
|
|
||||||
.search-wrap,
|
|
||||||
.search-wrap.wide,
|
|
||||||
.detail-alert-strip,
|
|
||||||
.month-chip,
|
|
||||||
.qa-filter,
|
|
||||||
.new-question-btn {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-combo {
|
|
||||||
justify-content: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-shell {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-meta {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-range-btn {
|
|
||||||
width: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-popover {
|
|
||||||
right: auto;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.range-combo {
|
|
||||||
display: grid;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-shell {
|
|
||||||
height: auto;
|
|
||||||
display: grid;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-meta {
|
|
||||||
width: 100%;
|
|
||||||
border-right: 0;
|
|
||||||
border-bottom: 1px solid #e2e8f0;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-tabs {
|
|
||||||
width: 100%;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.range-tabs button {
|
|
||||||
flex: 1;
|
|
||||||
padding: 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-popover {
|
|
||||||
width: min(336px, calc(100vw - 32px));
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-fields {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ function observeResize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.graph-eyebrow {
|
.graph-eyebrow {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
@@ -515,7 +515,7 @@ function observeResize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.inspector-title span {
|
.inspector-title span {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<div class="node-detail-panel">
|
<div class="node-detail-panel">
|
||||||
<section class="detail-section">
|
<section class="detail-section">
|
||||||
<div class="detail-section-head">
|
<div class="detail-section-head">
|
||||||
<strong>节点说明</strong>
|
<strong>节点摘要</strong>
|
||||||
<span>{{ safeNode.type || '实体' }}</span>
|
<span>{{ safeNode.type || '未知类型' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="descriptionItems.length" class="description-list">
|
<div v-if="descriptionItems.length" class="description-list">
|
||||||
<p v-for="(description, index) in descriptionItems" :key="index">
|
<p v-for="(description, index) in descriptionItems" :key="index">
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="detail-empty compact">
|
<div v-else class="detail-empty compact">
|
||||||
当前节点暂无 LightRAG 描述,完成新的归集后会从图谱属性中补充。
|
暂无描述,LightRAG 还没有为该节点生成可展示的摘要。
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -22,11 +22,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<dl class="property-grid">
|
<dl class="property-grid">
|
||||||
<div>
|
<div>
|
||||||
<dt>类型</dt>
|
<dt>节点类型</dt>
|
||||||
<dd>{{ safeNode.type || '实体' }}</dd>
|
<dd>{{ safeNode.type || '未知类型' }}</dd>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<dt>关系数</dt>
|
<dt>关联度</dt>
|
||||||
<dd>{{ safeNode.degree || 0 }}</dd>
|
<dd>{{ safeNode.degree || 0 }}</dd>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
<section class="detail-section relation-section">
|
<section class="detail-section relation-section">
|
||||||
<div class="detail-section-head">
|
<div class="detail-section-head">
|
||||||
<strong>关系语境</strong>
|
<strong>关联关系</strong>
|
||||||
<span>{{ relationRows.length }} 条</span>
|
<span>{{ relationRows.length }} 条</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="relationRows.length" class="relation-detail-list">
|
<div v-if="relationRows.length" class="relation-detail-list">
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="detail-empty compact">暂无关联关系。</div>
|
<div v-else class="detail-empty compact">暂无关联关系</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -139,7 +139,7 @@ const relationRows = computed(() => {
|
|||||||
raw: relation,
|
raw: relation,
|
||||||
peerName,
|
peerName,
|
||||||
type: String(relation.type || '关联').trim(),
|
type: String(relation.type || '关联').trim(),
|
||||||
directionLabel: isOutgoing ? '指向' : '来自',
|
directionLabel: isOutgoing ? '指向' : '来源',
|
||||||
description: String(relation.description || '').trim(),
|
description: String(relation.description || '').trim(),
|
||||||
keywords: dedupeTextItems(relation.keywords).slice(0, 6)
|
keywords: dedupeTextItems(relation.keywords).slice(0, 6)
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ function formatPropertyKey(key) {
|
|||||||
.description-list p {
|
.description-list p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 9px;
|
padding: 9px;
|
||||||
border: 1px solid #dbeafe;
|
border: 1px solid color-mix(in srgb, var(--theme-primary) 18%, #ffffff);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #1e293b;
|
color: #1e293b;
|
||||||
@@ -288,8 +288,8 @@ function formatPropertyKey(key) {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 7px;
|
padding: 0 7px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #e0f2fe;
|
background: var(--theme-primary-light-9);
|
||||||
color: #075985;
|
color: var(--theme-primary-active);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -317,7 +317,7 @@ function formatPropertyKey(key) {
|
|||||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||||
gap: 7px;
|
gap: 7px;
|
||||||
padding: 9px;
|
padding: 9px;
|
||||||
border: 1px solid #dbeafe;
|
border: 1px solid color-mix(in srgb, var(--theme-primary) 18%, #ffffff);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -326,8 +326,8 @@ function formatPropertyKey(key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.relation-detail-list button:hover {
|
.relation-detail-list button:hover {
|
||||||
border-color: #60a5fa;
|
border-color: color-mix(in srgb, var(--theme-primary) 38%, #ffffff);
|
||||||
background: #eff6ff;
|
background: var(--theme-primary-light-9);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ function formatPropertyKey(key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.relation-detail-list strong {
|
.relation-detail-list strong {
|
||||||
color: #1d4ed8;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.relation-detail-list p,
|
.relation-detail-list p,
|
||||||
@@ -359,8 +359,8 @@ function formatPropertyKey(key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.keyword-row span {
|
.keyword-row span {
|
||||||
background: #ecfdf5;
|
background: var(--theme-primary-light-9);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-empty {
|
.detail-empty {
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ function formatElapsed(startedAt, finishedAt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.info-title span {
|
.info-title span {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
}
|
}
|
||||||
@@ -129,8 +129,8 @@ function formatElapsed(startedAt, finishedAt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.info-title > strong.success {
|
.info-title > strong.success {
|
||||||
background: #dcfce7;
|
background: var(--success-soft);
|
||||||
color: #166534;
|
color: var(--success-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-title > strong.warning {
|
.info-title > strong.warning {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const model = computed(() => buildKnowledgeIngestLogModel(props.run))
|
|||||||
}
|
}
|
||||||
|
|
||||||
.eyebrow {
|
.eyebrow {
|
||||||
color: #0f766e;
|
color: var(--theme-primary-active);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ const model = computed(() => buildKnowledgeIngestLogModel(props.run))
|
|||||||
display: block;
|
display: block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
background: linear-gradient(90deg, #0f766e, #2563eb);
|
background: linear-gradient(90deg, var(--theme-primary-active), var(--theme-secondary));
|
||||||
transition: width 0.24s ease;
|
transition: width 0.24s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
|
|
||||||
|
import { useThemeColors } from '../../composables/useThemeColors.js'
|
||||||
|
|
||||||
const MAX_VISIBLE_NODES = 72
|
const MAX_VISIBLE_NODES = 72
|
||||||
const MAX_VISIBLE_EDGES = 180
|
const MAX_VISIBLE_EDGES = 180
|
||||||
const MAX_RELATION_PREVIEW = 40
|
const MAX_RELATION_PREVIEW = 40
|
||||||
|
|
||||||
const NODE_TONES = {
|
const BASE_NODE_TONES = {
|
||||||
hub: {
|
hub: {
|
||||||
fill: '#2563eb',
|
fill: '#2563eb',
|
||||||
stroke: '#dbeafe',
|
stroke: '#dbeafe',
|
||||||
@@ -12,10 +14,10 @@ const NODE_TONES = {
|
|||||||
shadow: 'rgba(37, 99, 235, 0.20)'
|
shadow: 'rgba(37, 99, 235, 0.20)'
|
||||||
},
|
},
|
||||||
strong: {
|
strong: {
|
||||||
fill: '#0f766e',
|
fill: '#3a7ca5',
|
||||||
stroke: '#ccfbf1',
|
stroke: '#eaf4fa',
|
||||||
halo: '#5eead4',
|
halo: '#d4e8f3',
|
||||||
shadow: 'rgba(15, 118, 110, 0.18)'
|
shadow: 'rgba(58, 124, 165, 0.18)'
|
||||||
},
|
},
|
||||||
accent: {
|
accent: {
|
||||||
fill: '#d97706',
|
fill: '#d97706',
|
||||||
@@ -40,8 +42,18 @@ const NODE_TONES = {
|
|||||||
export function useKnowledgeIngestGraph(props) {
|
export function useKnowledgeIngestGraph(props) {
|
||||||
const graphQuery = ref('')
|
const graphQuery = ref('')
|
||||||
const activeNodeId = ref('')
|
const activeNodeId = ref('')
|
||||||
|
const themeColors = useThemeColors()
|
||||||
|
|
||||||
const allRelations = computed(() => normalizeRelations(props.graph?.relations))
|
const allRelations = computed(() => normalizeRelations(props.graph?.relations))
|
||||||
|
const nodeTones = computed(() => ({
|
||||||
|
...BASE_NODE_TONES,
|
||||||
|
strong: {
|
||||||
|
fill: themeColors.value.chartPrimary,
|
||||||
|
stroke: themeColors.value.primarySoft,
|
||||||
|
halo: themeColors.value.primarySoft,
|
||||||
|
shadow: toRgba(themeColors.value.chartPrimary, 0.18)
|
||||||
|
}
|
||||||
|
}))
|
||||||
const rankedNodes = computed(() => buildRankedNodes(props.graph, allRelations.value))
|
const rankedNodes = computed(() => buildRankedNodes(props.graph, allRelations.value))
|
||||||
const visibleNodes = computed(() => {
|
const visibleNodes = computed(() => {
|
||||||
const query = graphQuery.value.toLowerCase()
|
const query = graphQuery.value.toLowerCase()
|
||||||
@@ -83,7 +95,7 @@ export function useKnowledgeIngestGraph(props) {
|
|||||||
selectedNodeRelations.value.filter((relation) => relation.source === selectedNode.value?.name)
|
selectedNodeRelations.value.filter((relation) => relation.source === selectedNode.value?.name)
|
||||||
)
|
)
|
||||||
const graphData = computed(() => ({
|
const graphData = computed(() => ({
|
||||||
nodes: visibleNodes.value.map((node) => toG6Node(node)),
|
nodes: visibleNodes.value.map((node) => toG6Node(node, nodeTones.value)),
|
||||||
edges: visibleRelations.value
|
edges: visibleRelations.value
|
||||||
.map((relation, index) => toG6Edge(relation, index, nodeIdByName.value))
|
.map((relation, index) => toG6Edge(relation, index, nodeIdByName.value))
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
@@ -179,9 +191,9 @@ function buildRankedNodes(graph, relations) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function toG6Node(node) {
|
function toG6Node(node, nodeTones) {
|
||||||
const tone = resolveNodeTone(node)
|
const tone = resolveNodeTone(node)
|
||||||
const palette = NODE_TONES[tone]
|
const palette = nodeTones[tone] || nodeTones.normal || BASE_NODE_TONES.normal
|
||||||
const size = clamp(34 + Math.sqrt(Math.max(node.degree, 1)) * 13, 38, node.rank === 1 ? 82 : 70)
|
const size = clamp(34 + Math.sqrt(Math.max(node.degree, 1)) * 13, 38, node.rank === 1 ? 82 : 70)
|
||||||
const opacity = node.matchesQuery ? 1 : 0.24
|
const opacity = node.matchesQuery ? 1 : 0.24
|
||||||
|
|
||||||
@@ -241,6 +253,20 @@ function toG6Node(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toRgba(hexColor, alpha) {
|
||||||
|
const normalized = String(hexColor || '').trim()
|
||||||
|
const matched = normalized.match(/^#([0-9a-f]{6})$/i)
|
||||||
|
if (!matched) {
|
||||||
|
return `rgba(58, 124, 165, ${alpha})`
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = matched[1]
|
||||||
|
const red = parseInt(value.slice(0, 2), 16)
|
||||||
|
const middle = parseInt(value.slice(2, 4), 16)
|
||||||
|
const blue = parseInt(value.slice(4, 6), 16)
|
||||||
|
return `rgba(${red}, ${middle}, ${blue}, ${alpha})`
|
||||||
|
}
|
||||||
|
|
||||||
function toG6Edge(relation, index, nodeIdByName) {
|
function toG6Edge(relation, index, nodeIdByName) {
|
||||||
const sourceId = nodeIdByName.get(relation.source)
|
const sourceId = nodeIdByName.get(relation.source)
|
||||||
const targetId = nodeIdByName.get(relation.target)
|
const targetId = nodeIdByName.get(relation.target)
|
||||||
|
|||||||
@@ -116,10 +116,10 @@ function handleCancel() {
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
border: 1px solid rgba(16, 185, 129, 0.14);
|
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.14);
|
||||||
border-radius: 24px;
|
border-radius: 8px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top left, rgba(16, 185, 129, 0.12), transparent 36%),
|
radial-gradient(circle at top left, rgba(var(--theme-primary-rgb, 58, 124, 165), 0.10), transparent 36%),
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(247, 250, 252, 0.98));
|
linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(247, 250, 252, 0.98));
|
||||||
box-shadow: 0 28px 56px rgba(15, 23, 42, 0.18);
|
box-shadow: 0 28px 56px rgba(15, 23, 42, 0.18);
|
||||||
}
|
}
|
||||||
@@ -136,18 +136,18 @@ function handleCancel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-badge.info {
|
.shared-confirm-badge.info {
|
||||||
background: rgba(59, 130, 246, 0.12);
|
background: var(--theme-primary-soft);
|
||||||
color: #1d4ed8;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-badge.warning {
|
.shared-confirm-badge.warning {
|
||||||
background: rgba(245, 158, 11, 0.14);
|
background: var(--warning-soft);
|
||||||
color: #b45309;
|
color: var(--warning-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-badge.danger {
|
.shared-confirm-badge.danger {
|
||||||
background: rgba(239, 68, 68, 0.12);
|
background: var(--danger-soft);
|
||||||
color: #dc2626;
|
color: var(--danger-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-card h4 {
|
.shared-confirm-card h4 {
|
||||||
@@ -197,7 +197,7 @@ function handleCancel() {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
border-radius: 14px;
|
border-radius: 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease, background 160ms ease;
|
transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease, background 160ms ease;
|
||||||
@@ -215,18 +215,18 @@ function handleCancel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-btn.confirm.primary {
|
.shared-confirm-btn.confirm.primary {
|
||||||
background: linear-gradient(135deg, #10b981, #059669);
|
background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-active));
|
||||||
box-shadow: 0 12px 24px rgba(5, 150, 105, 0.22);
|
box-shadow: 0 12px 24px rgba(var(--theme-primary-rgb, 58, 124, 165), 0.20);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-btn.confirm.danger {
|
.shared-confirm-btn.confirm.danger {
|
||||||
background: linear-gradient(135deg, #ef4444, #dc2626);
|
background: linear-gradient(135deg, var(--danger), var(--danger-hover));
|
||||||
box-shadow: 0 12px 24px rgba(220, 38, 38, 0.22);
|
box-shadow: 0 12px 24px rgba(var(--danger-rgb), 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-btn.cancel:hover:not(:disabled) {
|
.shared-confirm-btn.cancel:hover:not(:disabled) {
|
||||||
border-color: rgba(16, 185, 129, 0.3);
|
border-color: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.3);
|
||||||
color: #047857;
|
color: var(--theme-primary-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-btn.confirm:hover:not(:disabled) {
|
.shared-confirm-btn.confirm:hover:not(:disabled) {
|
||||||
@@ -259,7 +259,7 @@ function handleCancel() {
|
|||||||
width: min(360px, 100%);
|
width: min(360px, 100%);
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 12px;
|
border-radius: 6px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +281,7 @@ function handleCancel() {
|
|||||||
min-width: 76px;
|
min-width: 76px;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border-radius: 7px;
|
border-radius: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +292,7 @@ function handleCancel() {
|
|||||||
|
|
||||||
.shared-confirm-card {
|
.shared-confirm-card {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 20px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shared-confirm-card h4 {
|
.shared-confirm-card h4 {
|
||||||
|
|||||||
72
web/src/components/shared/EnterpriseSelect.vue
Normal file
72
web/src/components/shared/EnterpriseSelect.vue
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<ElSelect
|
||||||
|
class="enterprise-select"
|
||||||
|
popper-class="enterprise-select-popper"
|
||||||
|
:model-value="modelValue"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:disabled="disabled"
|
||||||
|
:clearable="clearable"
|
||||||
|
:filterable="filterable"
|
||||||
|
:size="size"
|
||||||
|
:teleported="teleported"
|
||||||
|
@change="handleChange"
|
||||||
|
>
|
||||||
|
<ElOption
|
||||||
|
v-for="option in normalizedOptions"
|
||||||
|
:key="option.key"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
:disabled="option.disabled"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: { type: [String, Number, Boolean], default: '' },
|
||||||
|
options: { type: Array, required: true },
|
||||||
|
placeholder: { type: String, default: '请选择' },
|
||||||
|
disabled: { type: Boolean, default: false },
|
||||||
|
clearable: { type: Boolean, default: false },
|
||||||
|
filterable: { type: Boolean, default: false },
|
||||||
|
size: { type: String, default: 'default' },
|
||||||
|
teleported: { type: Boolean, default: true }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue', 'change'])
|
||||||
|
|
||||||
|
const normalizedOptions = computed(() =>
|
||||||
|
props.options.map((option, index) => {
|
||||||
|
if (option && typeof option === 'object') {
|
||||||
|
const value = option.value ?? option.label ?? ''
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: `${value}-${index}`,
|
||||||
|
label: String(option.label ?? value),
|
||||||
|
value,
|
||||||
|
disabled: Boolean(option.disabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: `${option}-${index}`,
|
||||||
|
label: String(option),
|
||||||
|
value: option,
|
||||||
|
disabled: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
function handleChange(value) {
|
||||||
|
emit('update:modelValue', value)
|
||||||
|
emit('change', value)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.enterprise-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -54,7 +54,7 @@ const props = defineProps({
|
|||||||
artLabel: { type: String, default: 'EMPTY' },
|
artLabel: { type: String, default: 'EMPTY' },
|
||||||
actionLabel: { type: String, default: '' },
|
actionLabel: { type: String, default: '' },
|
||||||
actionIcon: { type: String, default: '' },
|
actionIcon: { type: String, default: '' },
|
||||||
tone: { type: String, default: 'emerald' },
|
tone: { type: String, default: 'theme' },
|
||||||
tips: {
|
tips: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
@@ -66,11 +66,11 @@ defineEmits(['action'])
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.table-empty-state {
|
.table-empty-state {
|
||||||
--accent: #10b981;
|
--accent: var(--theme-primary);
|
||||||
--accent-deep: #059669;
|
--accent-deep: var(--theme-primary-active);
|
||||||
--accent-soft: rgba(16, 185, 129, 0.16);
|
--accent-soft: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.16);
|
||||||
--accent-line: rgba(16, 185, 129, 0.24);
|
--accent-line: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.24);
|
||||||
--accent-mist: rgba(16, 185, 129, 0.08);
|
--accent-mist: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -82,20 +82,21 @@ defineEmits(['action'])
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-empty-state.theme,
|
||||||
.table-empty-state.sky {
|
.table-empty-state.sky {
|
||||||
--accent: #0ea5e9;
|
--accent: var(--theme-primary);
|
||||||
--accent-deep: #0284c7;
|
--accent-deep: var(--theme-primary-active);
|
||||||
--accent-soft: rgba(14, 165, 233, 0.16);
|
--accent-soft: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.16);
|
||||||
--accent-line: rgba(14, 165, 233, 0.24);
|
--accent-line: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.24);
|
||||||
--accent-mist: rgba(14, 165, 233, 0.08);
|
--accent-mist: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-empty-state.amber {
|
.table-empty-state.amber {
|
||||||
--accent: #f59e0b;
|
--accent: var(--warning);
|
||||||
--accent-deep: #d97706;
|
--accent-deep: var(--warning-hover);
|
||||||
--accent-soft: rgba(245, 158, 11, 0.16);
|
--accent-soft: rgba(var(--warning-rgb), 0.16);
|
||||||
--accent-line: rgba(245, 158, 11, 0.24);
|
--accent-line: rgba(var(--warning-rgb), 0.24);
|
||||||
--accent-mist: rgba(245, 158, 11, 0.08);
|
--accent-mist: rgba(var(--warning-rgb), 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-empty-state.slate {
|
.table-empty-state.slate {
|
||||||
@@ -106,6 +107,14 @@ defineEmits(['action'])
|
|||||||
--accent-mist: rgba(100, 116, 139, 0.08);
|
--accent-mist: rgba(100, 116, 139, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-empty-state.success {
|
||||||
|
--accent: var(--success);
|
||||||
|
--accent-deep: var(--success-hover);
|
||||||
|
--accent-soft: rgba(var(--success-rgb), 0.16);
|
||||||
|
--accent-line: rgba(var(--success-rgb), 0.24);
|
||||||
|
--accent-mist: rgba(var(--success-rgb), 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
.table-empty-state__art {
|
.table-empty-state__art {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: min(240px, 100%);
|
width: min(240px, 100%);
|
||||||
@@ -144,7 +153,7 @@ defineEmits(['action'])
|
|||||||
height: 82px;
|
height: 82px;
|
||||||
padding: 14px 14px 12px;
|
padding: 14px 14px 12px;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.88);
|
border: 1px solid rgba(255, 255, 255, 0.88);
|
||||||
border-radius: 18px;
|
border-radius: 8px;
|
||||||
background:
|
background:
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(245, 248, 250, 0.94));
|
linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(245, 248, 250, 0.94));
|
||||||
box-shadow: 0 18px 30px rgba(15, 23, 42, 0.08);
|
box-shadow: 0 18px 30px rgba(15, 23, 42, 0.08);
|
||||||
@@ -208,7 +217,7 @@ defineEmits(['action'])
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.86);
|
border: 1px solid rgba(255, 255, 255, 0.86);
|
||||||
border-radius: 24px;
|
border-radius: 10px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at 30% 20%, rgba(255, 255, 255, 0.88), rgba(255, 255, 255, 0.3) 42%),
|
radial-gradient(circle at 30% 20%, rgba(255, 255, 255, 0.88), rgba(255, 255, 255, 0.3) 42%),
|
||||||
linear-gradient(135deg, var(--accent), var(--accent-deep));
|
linear-gradient(135deg, var(--accent), var(--accent-deep));
|
||||||
@@ -287,7 +296,7 @@ defineEmits(['action'])
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: 12px;
|
border-radius: 6px;
|
||||||
background: linear-gradient(135deg, var(--accent), var(--accent-deep));
|
background: linear-gradient(135deg, var(--accent), var(--accent-deep));
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -316,13 +325,13 @@ defineEmits(['action'])
|
|||||||
.table-empty-state__sheet {
|
.table-empty-state__sheet {
|
||||||
width: 110px;
|
width: 110px;
|
||||||
height: 74px;
|
height: 74px;
|
||||||
border-radius: 16px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-empty-state__badge {
|
.table-empty-state__badge {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
border-radius: 20px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-empty-state__badge i {
|
.table-empty-state__badge i {
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
tone: {
|
tone: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'emerald',
|
default: 'theme',
|
||||||
validator: (value) => ['emerald', 'sky'].includes(value)
|
validator: (value) => ['theme', 'sky', 'success'].includes(value)
|
||||||
},
|
},
|
||||||
title: { type: String, default: '' },
|
title: { type: String, default: '' },
|
||||||
message: { type: String, default: '' },
|
message: { type: String, default: '' },
|
||||||
@@ -45,15 +45,21 @@ const ariaLabel = computed(() => [props.title, props.message].filter(Boolean).jo
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.table-loading {
|
.table-loading {
|
||||||
--accent: #10b981;
|
--accent: var(--theme-primary);
|
||||||
--accent-deep: #059669;
|
--accent-deep: var(--theme-primary-active);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-loading.theme,
|
||||||
.table-loading.sky {
|
.table-loading.sky {
|
||||||
--accent: #0ea5e9;
|
--accent: var(--theme-primary);
|
||||||
--accent-deep: #0284c7;
|
--accent-deep: var(--theme-primary-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-loading.success {
|
||||||
|
--accent: var(--success);
|
||||||
|
--accent-deep: var(--success-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-loading.panel {
|
.table-loading.panel {
|
||||||
@@ -96,7 +102,7 @@ const ariaLabel = computed(() => [props.title, props.message].filter(Boolean).jo
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color: #0369a1;
|
color: #255b7d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-loading__spinner {
|
.table-loading__spinner {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { workbenchIconMap } from '../../utils/workbenchIconAssets.js'
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
iconKey: { type: String, required: true },
|
iconKey: { type: String, required: true },
|
||||||
color: { type: String, default: '#10b981' },
|
color: { type: String, default: 'var(--theme-primary)' },
|
||||||
accent: { type: String, default: '' }
|
accent: { type: String, default: '' }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
623
web/src/components/travel/TravelReimbursementInsightPanel.vue
Normal file
623
web/src/components/travel/TravelReimbursementInsightPanel.vue
Normal file
@@ -0,0 +1,623 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="insight-panel-shell"
|
||||||
|
:class="{ collapsed: !ui.showInsightPanel }"
|
||||||
|
:aria-hidden="(!ui.showInsightPanel).toString()"
|
||||||
|
>
|
||||||
|
<aside class="insight-panel">
|
||||||
|
<div
|
||||||
|
v-if="!ui.isKnowledgeSession"
|
||||||
|
class="insight-head"
|
||||||
|
:class="{ 'review-mode': ui.activeReviewPayload || ui.isReviewFlowDrawer }"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div v-if="!ui.activeReviewPayload && !ui.isReviewFlowDrawer" class="insight-head-eyebrow">
|
||||||
|
<span class="intent-pill" :class="ui.currentInsight.intent">{{ ui.currentIntentLabel }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else class="review-insight-title-row">
|
||||||
|
<div class="review-insight-title-copy">
|
||||||
|
<h3>{{ ui.reviewDrawerTitle }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3 v-if="!ui.activeReviewPayload && !ui.isReviewFlowDrawer">{{ ui.currentInsight.title }}</h3>
|
||||||
|
<p v-if="!ui.activeReviewPayload && !ui.isReviewFlowDrawer">{{ ui.currentInsight.summary }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="ui.activeReviewPayload || ui.isReviewFlowDrawer" class="review-insight-tools">
|
||||||
|
<button
|
||||||
|
v-if="ui.activeReviewPayload && ui.reviewOverviewDrawerAvailable"
|
||||||
|
type="button"
|
||||||
|
class="review-insight-switch-icon-btn"
|
||||||
|
:class="{
|
||||||
|
available: true,
|
||||||
|
active: ui.isReviewOverviewDrawer
|
||||||
|
}"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy"
|
||||||
|
title="报销识别核对"
|
||||||
|
aria-label="报销识别核对"
|
||||||
|
@click="ui.switchToReviewOverviewDrawer"
|
||||||
|
>
|
||||||
|
<i :class="ui.isReviewOverviewDrawer ? 'mdi mdi-clipboard-check' : 'mdi mdi-clipboard-check-outline'"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
v-if="ui.activeReviewPayload && ui.reviewDocumentDrawerAvailable"
|
||||||
|
type="button"
|
||||||
|
class="review-insight-switch-icon-btn"
|
||||||
|
:class="{
|
||||||
|
available: ui.reviewDocumentDrawerAvailable,
|
||||||
|
active: ui.reviewDocumentDrawerAvailable && ui.isReviewDocumentDrawer
|
||||||
|
}"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy"
|
||||||
|
title="单据识别"
|
||||||
|
aria-label="单据识别"
|
||||||
|
@click="ui.toggleReviewDocumentDrawer"
|
||||||
|
>
|
||||||
|
<i :class="ui.reviewDocumentDrawerIcon"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
v-if="ui.activeReviewPayload && ui.reviewRiskDrawerAvailable"
|
||||||
|
type="button"
|
||||||
|
class="review-insight-switch-icon-btn risk"
|
||||||
|
:class="{
|
||||||
|
available: ui.reviewRiskDrawerAvailable,
|
||||||
|
active: ui.reviewRiskDrawerAvailable && ui.isReviewRiskDrawer
|
||||||
|
}"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy"
|
||||||
|
title="显示风险"
|
||||||
|
aria-label="显示风险"
|
||||||
|
@click="ui.toggleReviewRiskDrawer"
|
||||||
|
>
|
||||||
|
<i :class="ui.reviewRiskDrawerIcon"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="review-insight-switch-icon-btn flow"
|
||||||
|
:class="{
|
||||||
|
available: ui.reviewFlowDrawerAvailable,
|
||||||
|
active: ui.reviewFlowDrawerAvailable && ui.isReviewFlowDrawer,
|
||||||
|
running: ui.flowOverallStatusTone === 'running'
|
||||||
|
}"
|
||||||
|
:disabled="!ui.reviewFlowDrawerAvailable || ui.submitting || ui.reviewActionBusy"
|
||||||
|
title="调用流程"
|
||||||
|
aria-label="调用流程"
|
||||||
|
@click="ui.toggleReviewFlowDrawer"
|
||||||
|
>
|
||||||
|
<i :class="ui.reviewFlowDrawerIcon"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="confidence-card" v-if="!ui.activeReviewPayload && !ui.isReviewFlowDrawer">
|
||||||
|
<span>{{ ui.currentInsight.metricLabel }}</span>
|
||||||
|
<strong>{{ ui.currentInsight.metricValue }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Transition name="insight-switch" mode="out-in">
|
||||||
|
<div
|
||||||
|
:key="`${ui.activeSessionType}-${ui.currentInsight.intent}-${ui.currentInsight.title}-${ui.reviewDrawerMode}`"
|
||||||
|
class="insight-body"
|
||||||
|
:class="{ 'document-review-body': ui.isReviewDocumentDrawer }"
|
||||||
|
>
|
||||||
|
<template v-if="ui.isKnowledgeSession">
|
||||||
|
<section class="insight-card knowledge-hot-card">
|
||||||
|
<div class="card-head">
|
||||||
|
<h4>热门问题 Top 10</h4>
|
||||||
|
</div>
|
||||||
|
<div class="knowledge-question-list">
|
||||||
|
<button
|
||||||
|
v-for="(item, index) in ui.hotKnowledgeQuestions"
|
||||||
|
:key="item"
|
||||||
|
type="button"
|
||||||
|
class="knowledge-question-btn"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy || ui.deleteSessionBusy || ui.sessionSwitchBusy"
|
||||||
|
@click="ui.askHotKnowledgeQuestion(item)"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="knowledge-question-index"
|
||||||
|
:class="ui.resolveKnowledgeRankTone(index)"
|
||||||
|
>
|
||||||
|
{{ ui.resolveKnowledgeRankLabel(index) }}
|
||||||
|
</span>
|
||||||
|
<span class="knowledge-question-copy">{{ item }}</span>
|
||||||
|
<i class="mdi mdi-arrow-top-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="ui.isReviewFlowDrawer">
|
||||||
|
<section class="review-flow-panel">
|
||||||
|
<div class="review-flow-summary">
|
||||||
|
<span class="flow-status-chip" :class="ui.flowOverallStatusTone">{{ ui.flowOverallStatusText }}</span>
|
||||||
|
<span>总耗时 {{ ui.flowTotalDurationText }}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="flow-icon-btn"
|
||||||
|
:disabled="!ui.flowRunId || ui.flowRefreshBusy"
|
||||||
|
title="刷新流程"
|
||||||
|
aria-label="刷新流程"
|
||||||
|
@click="ui.refreshFlowRunDetail"
|
||||||
|
>
|
||||||
|
<i :class="ui.flowRefreshBusy ? 'mdi mdi-loading mdi-spin' : 'mdi mdi-refresh'"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="ui.flowSteps.length" class="review-flow-list">
|
||||||
|
<article
|
||||||
|
v-for="(step, index) in ui.flowSteps"
|
||||||
|
:key="step.key"
|
||||||
|
class="flow-step-item"
|
||||||
|
:class="step.status"
|
||||||
|
>
|
||||||
|
<div class="flow-step-rail">
|
||||||
|
<span>{{ index + 1 }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flow-step-card">
|
||||||
|
<header>
|
||||||
|
<strong>{{ step.title }}</strong>
|
||||||
|
<div class="flow-step-side">
|
||||||
|
<span class="flow-step-status" :class="step.status">{{ ui.resolveFlowStepStatusLabel(step) }}</span>
|
||||||
|
<time>{{ ui.formatFlowStepDuration(step) }}</time>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<p class="flow-step-tool">工具:{{ step.tool }}</p>
|
||||||
|
<p class="flow-step-detail">{{ ui.resolveFlowStepDetail(step) }}</p>
|
||||||
|
<p v-if="step.error" class="flow-step-error">{{ step.error }}</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="flow-empty-state compact">
|
||||||
|
<i class="mdi mdi-timeline-question-outline"></i>
|
||||||
|
<strong>暂无识别流程</strong>
|
||||||
|
<p>发起识别后,这里会显示调用步骤和耗时。</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="ui.currentInsight.intent === 'agent' && ui.currentInsight.agent">
|
||||||
|
<template v-if="ui.activeReviewPayload">
|
||||||
|
<template v-if="ui.reviewOverviewDrawerAvailable && !ui.isReviewDocumentDrawer && !ui.isReviewRiskDrawer && !ui.isReviewFlowDrawer">
|
||||||
|
<section class="review-side-card review-side-overview-card">
|
||||||
|
<div class="review-side-intent-row">
|
||||||
|
<i class="mdi mdi-account-outline"></i>
|
||||||
|
<span>用户意图:</span>
|
||||||
|
<strong>{{ ui.reviewIntentText }}</strong>
|
||||||
|
</div>
|
||||||
|
<section class="review-side-grid compact">
|
||||||
|
<article
|
||||||
|
v-for="item in ui.reviewFactCards"
|
||||||
|
:key="item.key"
|
||||||
|
class="review-side-metric-card"
|
||||||
|
:class="{
|
||||||
|
editable: item.editor,
|
||||||
|
editing: ui.reviewInlineEditorKey === item.key,
|
||||||
|
invalid: Boolean(ui.reviewInlineErrors[item.key]),
|
||||||
|
wide: item.wide
|
||||||
|
}"
|
||||||
|
@click="ui.openInlineReviewEditor(item.key)"
|
||||||
|
>
|
||||||
|
<span class="review-side-metric-icon">
|
||||||
|
<i :class="item.icon"></i>
|
||||||
|
</span>
|
||||||
|
<div class="review-side-metric-copy">
|
||||||
|
<small>{{ item.label }}</small>
|
||||||
|
<template v-if="ui.reviewInlineEditorKey === item.key && item.editor === 'date'">
|
||||||
|
<input
|
||||||
|
v-model="ui.reviewInlineForm[item.modelKey]"
|
||||||
|
class="review-inline-input"
|
||||||
|
:class="{ invalid: Boolean(ui.reviewInlineErrors[item.key]) }"
|
||||||
|
type="text"
|
||||||
|
:placeholder="`仅支持 ${ui.DATE_INPUT_FORMAT}`"
|
||||||
|
@click.stop
|
||||||
|
@input="ui.clearInlineReviewFieldError(item.key)"
|
||||||
|
@blur="ui.commitInlineReviewEditor"
|
||||||
|
@keydown.enter.prevent="ui.commitInlineReviewEditor"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="ui.reviewInlineEditorKey === item.key && item.editor === 'amount'">
|
||||||
|
<input
|
||||||
|
v-model="ui.reviewInlineForm[item.modelKey]"
|
||||||
|
class="review-inline-input"
|
||||||
|
:class="{ invalid: Boolean(ui.reviewInlineErrors[item.key]) }"
|
||||||
|
type="text"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
@click.stop
|
||||||
|
@input="ui.clearInlineReviewFieldError(item.key)"
|
||||||
|
@blur="ui.commitInlineReviewEditor"
|
||||||
|
@keydown.enter.prevent="ui.commitInlineReviewEditor"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="ui.reviewInlineEditorKey === item.key && item.editor === 'text'">
|
||||||
|
<input
|
||||||
|
v-model="ui.reviewInlineForm[item.modelKey]"
|
||||||
|
class="review-inline-input"
|
||||||
|
:class="{ invalid: Boolean(ui.reviewInlineErrors[item.key]) }"
|
||||||
|
type="text"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
@click.stop
|
||||||
|
@input="ui.clearInlineReviewFieldError(item.key)"
|
||||||
|
@blur="ui.commitInlineReviewEditor"
|
||||||
|
@keydown.enter.prevent="ui.commitInlineReviewEditor"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="ui.reviewInlineEditorKey === item.key && item.editor === 'textarea'">
|
||||||
|
<textarea
|
||||||
|
v-model="ui.reviewInlineForm[item.modelKey]"
|
||||||
|
class="review-inline-input review-inline-textarea"
|
||||||
|
:class="{ invalid: Boolean(ui.reviewInlineErrors[item.key]) }"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
rows="3"
|
||||||
|
@click.stop
|
||||||
|
@input="ui.clearInlineReviewFieldError(item.key)"
|
||||||
|
@blur="ui.commitInlineReviewEditor"
|
||||||
|
@keydown.enter.stop
|
||||||
|
></textarea>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="ui.reviewInlineEditorKey === item.key && item.editor === 'select'">
|
||||||
|
<div class="review-inline-select-list" @click.stop>
|
||||||
|
<button
|
||||||
|
v-for="scene in ui.REVIEW_SCENE_OPTIONS"
|
||||||
|
:key="scene"
|
||||||
|
type="button"
|
||||||
|
class="review-inline-select-option"
|
||||||
|
:class="{ active: ui.reviewInlineForm.scene_label === scene }"
|
||||||
|
@click.stop="ui.selectInlineScene(scene)"
|
||||||
|
>
|
||||||
|
{{ scene }}
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
v-if="ui.reviewInlineForm.scene_label === ui.REVIEW_SCENE_OTHER_OPTION"
|
||||||
|
v-model="ui.reviewInlineForm.reason_value"
|
||||||
|
class="review-inline-input review-inline-select-custom"
|
||||||
|
:class="{ invalid: Boolean(ui.reviewInlineErrors[item.key]) }"
|
||||||
|
type="text"
|
||||||
|
placeholder="请输入具体事由"
|
||||||
|
@click.stop
|
||||||
|
@input="ui.clearInlineReviewFieldError(item.key)"
|
||||||
|
@blur="ui.commitInlineReviewEditor"
|
||||||
|
@keydown.enter.prevent="ui.commitInlineReviewEditor"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<strong v-else :title="item.value">{{ item.value }}</strong>
|
||||||
|
<span v-if="ui.reviewInlineErrors[item.key]" class="review-inline-error">
|
||||||
|
{{ ui.reviewInlineErrors[item.key] }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span v-if="item.key !== 'attachments'" class="review-side-edit-hint">修改</span>
|
||||||
|
<span v-else class="review-side-edit-hint upload">{{ ui.reviewInlinePendingFiles.length ? '已选择' : '上传' }}</span>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="review-side-card">
|
||||||
|
<div class="review-side-head">
|
||||||
|
<strong>报销分类</strong>
|
||||||
|
<span class="review-side-confidence">置信度 {{ ui.reviewPanelConfidence }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="review-side-category-grid">
|
||||||
|
<button
|
||||||
|
v-for="item in ui.reviewCategoryOptions"
|
||||||
|
:key="item.key"
|
||||||
|
type="button"
|
||||||
|
class="review-side-category-card"
|
||||||
|
:class="{ active: item.active }"
|
||||||
|
@click="ui.selectReviewCategory(item)"
|
||||||
|
>
|
||||||
|
<div class="review-side-category-copy">
|
||||||
|
<strong>{{ item.label }}</strong>
|
||||||
|
<p>{{ item.is_other && ui.reviewSelectedOtherCategory ? ui.reviewSelectedOtherCategory : item.caption }}</p>
|
||||||
|
</div>
|
||||||
|
<i v-if="item.active" class="mdi mdi-check-circle review-side-group-check"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div v-if="ui.reviewOtherCategoryOpen" class="review-other-category-popover">
|
||||||
|
<button
|
||||||
|
v-for="item in ui.reviewOtherCategoryOptions"
|
||||||
|
:key="item.key"
|
||||||
|
type="button"
|
||||||
|
class="review-other-category-option"
|
||||||
|
:class="{ active: ui.reviewSelectedOtherCategory === item.label }"
|
||||||
|
@click="ui.selectReviewOtherCategory(item)"
|
||||||
|
>
|
||||||
|
{{ item.label }} · {{ item.confidenceLabel }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="ui.isReviewFlowDrawer">
|
||||||
|
<section class="review-flow-panel">
|
||||||
|
<div class="review-flow-summary">
|
||||||
|
<span class="flow-status-chip" :class="ui.flowOverallStatusTone">{{ ui.flowOverallStatusText }}</span>
|
||||||
|
<span>总耗时 {{ ui.flowTotalDurationText }}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="flow-icon-btn"
|
||||||
|
:disabled="!ui.flowRunId || ui.flowRefreshBusy"
|
||||||
|
title="刷新流程"
|
||||||
|
aria-label="刷新流程"
|
||||||
|
@click="ui.refreshFlowRunDetail"
|
||||||
|
>
|
||||||
|
<i :class="ui.flowRefreshBusy ? 'mdi mdi-loading mdi-spin' : 'mdi mdi-refresh'"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="ui.flowSteps.length" class="review-flow-list">
|
||||||
|
<article
|
||||||
|
v-for="(step, index) in ui.flowSteps"
|
||||||
|
:key="step.key"
|
||||||
|
class="flow-step-item"
|
||||||
|
:class="step.status"
|
||||||
|
>
|
||||||
|
<div class="flow-step-rail">
|
||||||
|
<span>{{ index + 1 }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flow-step-card">
|
||||||
|
<header>
|
||||||
|
<strong>{{ step.title }}</strong>
|
||||||
|
<div class="flow-step-side">
|
||||||
|
<span class="flow-step-status" :class="step.status">{{ ui.resolveFlowStepStatusLabel(step) }}</span>
|
||||||
|
<time>{{ ui.formatFlowStepDuration(step) }}</time>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<p class="flow-step-tool">工具:{{ step.tool }}</p>
|
||||||
|
<p class="flow-step-detail">{{ ui.resolveFlowStepDetail(step) }}</p>
|
||||||
|
<p v-if="step.error" class="flow-step-error">{{ step.error }}</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="flow-empty-state compact">
|
||||||
|
<i class="mdi mdi-timeline-question-outline"></i>
|
||||||
|
<strong>暂无识别流程</strong>
|
||||||
|
<p>发起识别后,这里会显示调用步骤和耗时。</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="ui.isReviewDocumentDrawer">
|
||||||
|
<section class="review-side-card review-document-switch-card review-ticket-drawer">
|
||||||
|
<div class="review-side-head review-document-switch-head">
|
||||||
|
<div class="review-side-head-copy">
|
||||||
|
<strong>票据识别结果卡片</strong>
|
||||||
|
<p>逐张查看 OCR 结果,可直接修正后再切回核对滑窗。</p>
|
||||||
|
</div>
|
||||||
|
<div class="review-document-nav">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="review-document-nav-btn"
|
||||||
|
:disabled="ui.activeReviewDocumentIndex === 0"
|
||||||
|
aria-label="上一张票据"
|
||||||
|
@click="ui.goReviewDocument(-1)"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-chevron-left"></i>
|
||||||
|
</button>
|
||||||
|
<span>{{ ui.activeReviewDocumentIndex + 1 }} / {{ ui.reviewDocumentCount }}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="review-document-nav-btn"
|
||||||
|
:disabled="ui.activeReviewDocumentIndex >= ui.reviewDocumentCount - 1"
|
||||||
|
aria-label="下一张票据"
|
||||||
|
@click="ui.goReviewDocument(1)"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="ui.activeReviewDocument" class="review-document-stage">
|
||||||
|
<div class="review-document-stage-head">
|
||||||
|
<div class="review-document-stage-copy">
|
||||||
|
<strong :title="ui.activeReviewDocument.filename">{{ ui.activeReviewDocument.filename }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="review-document-meta-chip-row">
|
||||||
|
<span class="review-document-meta-chip">{{ ui.activeReviewDocument.documentTypeLabel }}</span>
|
||||||
|
<span class="review-document-meta-chip">{{ ui.activeReviewDocument.expenseTypeLabel }}</span>
|
||||||
|
<span class="review-document-meta-chip confidence">{{ ui.activeReviewDocument.confidenceLabel }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="review-document-scroll">
|
||||||
|
<div
|
||||||
|
class="review-document-preview-card"
|
||||||
|
:class="[
|
||||||
|
ui.activeReviewDocumentPreview?.kind || 'file',
|
||||||
|
{ clickable: ui.canPreviewActiveReviewDocument }
|
||||||
|
]"
|
||||||
|
:role="ui.canPreviewActiveReviewDocument ? 'button' : null"
|
||||||
|
:tabindex="ui.canPreviewActiveReviewDocument ? 0 : null"
|
||||||
|
@click="ui.canPreviewActiveReviewDocument ? ui.openActiveReviewDocumentPreview() : null"
|
||||||
|
@keydown.enter.prevent="ui.canPreviewActiveReviewDocument ? ui.openActiveReviewDocumentPreview() : null"
|
||||||
|
@keydown.space.prevent="ui.canPreviewActiveReviewDocument ? ui.openActiveReviewDocumentPreview() : null"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="ui.activeReviewDocumentPreview?.kind === 'image' && ui.activeReviewDocumentPreview?.url"
|
||||||
|
:src="ui.activeReviewDocumentPreview.url"
|
||||||
|
:alt="ui.activeReviewDocument.filename"
|
||||||
|
/>
|
||||||
|
<div v-else-if="ui.activeReviewDocumentPreview?.kind === 'pdf'" class="review-document-preview-placeholder">
|
||||||
|
<i class="mdi mdi-file-pdf-box"></i>
|
||||||
|
<strong>PDF 票据文件</strong>
|
||||||
|
<p>当前文件还没有生成图片预览,可先核对下方识别字段。</p>
|
||||||
|
</div>
|
||||||
|
<div v-else class="review-document-preview-placeholder">
|
||||||
|
<i class="mdi mdi-file-search-outline"></i>
|
||||||
|
<strong>当前无可预览票据</strong>
|
||||||
|
<p>这张票据还没有可用预览,可先核对下方识别字段。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="review-document-edit-field summary">
|
||||||
|
<span>票据摘要</span>
|
||||||
|
<textarea
|
||||||
|
v-model="ui.activeReviewDocument.summary"
|
||||||
|
rows="3"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy"
|
||||||
|
placeholder="可根据票据图片修正 OCR 摘要"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="review-document-edit-field">
|
||||||
|
<span>票据场景</span>
|
||||||
|
<input
|
||||||
|
v-model="ui.activeReviewDocument.scene_label"
|
||||||
|
type="text"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy"
|
||||||
|
placeholder="例如:出租车/网约车票据 / 火车/高铁票"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div v-if="ui.activeReviewDocument.fields.length" class="review-document-edit-grid">
|
||||||
|
<label
|
||||||
|
v-for="field in ui.activeReviewDocument.fields"
|
||||||
|
:key="`${ui.activeReviewDocument.filename}-${field.label}`"
|
||||||
|
class="review-document-edit-field"
|
||||||
|
>
|
||||||
|
<span>{{ field.label }}</span>
|
||||||
|
<input
|
||||||
|
v-model="field.value"
|
||||||
|
type="text"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy"
|
||||||
|
:placeholder="`修正 ${field.label}`"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div v-else class="review-side-empty compact">
|
||||||
|
<span class="review-side-empty-icon">
|
||||||
|
<i class="mdi mdi-text-recognition"></i>
|
||||||
|
</span>
|
||||||
|
<strong>暂无结构化字段</strong>
|
||||||
|
<p>当前只返回了摘要信息,你仍然可以直接修改上面的票据摘要。</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="ui.activeReviewDocument.warnings?.length" class="review-document-warning-list">
|
||||||
|
<article
|
||||||
|
v-for="warning in ui.activeReviewDocument.warnings"
|
||||||
|
:key="`${ui.activeReviewDocument.filename}-${warning}`"
|
||||||
|
class="review-document-warning-item"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-alert-circle-outline"></i>
|
||||||
|
<span>{{ warning }}</span>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="ui.isReviewRiskDrawer">
|
||||||
|
<section class="review-side-card review-side-risk-card">
|
||||||
|
<div class="review-side-head">
|
||||||
|
<div class="review-side-head-copy">
|
||||||
|
<strong>差旅合规提示</strong>
|
||||||
|
<p>结合票据识别结果与差旅规则,逐项查看需要处理的风险点。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="review-side-risk-summary">{{ ui.reviewRiskSummary }}</p>
|
||||||
|
<div v-if="ui.reviewRiskItems.length" class="review-side-risk-list">
|
||||||
|
<button
|
||||||
|
v-for="item in ui.reviewRiskItems"
|
||||||
|
:key="item.key"
|
||||||
|
type="button"
|
||||||
|
class="review-side-risk-item"
|
||||||
|
:class="item.level"
|
||||||
|
@click="ui.appendReviewRiskBriefToConversation(item)"
|
||||||
|
>
|
||||||
|
<span class="review-side-risk-icon" :title="item.levelLabel">
|
||||||
|
<i :class="item.icon"></i>
|
||||||
|
</span>
|
||||||
|
<span class="review-side-risk-copy">
|
||||||
|
<strong>{{ item.title }}</strong>
|
||||||
|
<p>{{ item.summary }}</p>
|
||||||
|
</span>
|
||||||
|
<span class="review-side-risk-meta">
|
||||||
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="ui.reviewRiskEmpty" class="review-side-empty">
|
||||||
|
<span class="review-side-empty-icon">
|
||||||
|
<i class="mdi mdi-shield-check-outline"></i>
|
||||||
|
</span>
|
||||||
|
<strong>暂无风险提示</strong>
|
||||||
|
<p>当前没有需要额外处理的结构化风险点。</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<button
|
||||||
|
v-if="ui.reviewHasUnsavedChanges"
|
||||||
|
type="button"
|
||||||
|
class="review-side-save-pill"
|
||||||
|
:disabled="ui.reviewActionBusy || ui.submitting"
|
||||||
|
@click="ui.saveInlineReviewChanges"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-content-save-outline"></i>
|
||||||
|
保存右侧修改
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<section v-if="ui.currentInsight.agent.citations?.length && !ui.currentInsight.agent.queryPayload && !ui.activeReviewPayload" class="insight-card">
|
||||||
|
<div class="card-head">
|
||||||
|
<h4>制度依据</h4>
|
||||||
|
</div>
|
||||||
|
<div class="citation-stack">
|
||||||
|
<article v-for="item in ui.currentInsight.agent.citations" :key="item.code" class="citation-card">
|
||||||
|
<header>
|
||||||
|
<strong>{{ item.title }}</strong>
|
||||||
|
<span>{{ item.version || item.source_type }}</span>
|
||||||
|
</header>
|
||||||
|
<p>{{ item.excerpt || item.code }}</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<template v-if="!ui.activeReviewPayload">
|
||||||
|
<section class="insight-card primary">
|
||||||
|
<div class="card-head">
|
||||||
|
<h4>识别结果</h4>
|
||||||
|
</div>
|
||||||
|
<div class="note-block">
|
||||||
|
<strong>{{ ui.currentInsight.title }}</strong>
|
||||||
|
<p>{{ ui.currentInsight.summary }}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section v-if="ui.currentInsight.agent.riskFlags?.length" class="insight-card">
|
||||||
|
<div class="card-head">
|
||||||
|
<h4>风险标签</h4>
|
||||||
|
</div>
|
||||||
|
<div class="capability-chip-row">
|
||||||
|
<span v-for="item in ui.currentInsight.agent.riskFlags" :key="item" class="risk-chip">{{ item }}</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'TravelReimbursementInsightPanel',
|
||||||
|
props: {
|
||||||
|
ui: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/components/travel-reimbursement-insight-panel.css"></style>
|
||||||
430
web/src/components/travel/TravelReimbursementMessageItem.vue
Normal file
430
web/src/components/travel/TravelReimbursementMessageItem.vue
Normal file
@@ -0,0 +1,430 @@
|
|||||||
|
<template>
|
||||||
|
<article
|
||||||
|
class="message-row"
|
||||||
|
:class="message.role"
|
||||||
|
>
|
||||||
|
<span class="message-avatar">
|
||||||
|
<img
|
||||||
|
:src="message.role === 'assistant' ? ui.aiAvatar : ui.userAvatar"
|
||||||
|
:alt="message.role === 'assistant' ? '财务助手头像' : '用户头像'"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="message-bubble" :class="ui.buildMessageBubbleClass(message)">
|
||||||
|
<header class="message-meta">
|
||||||
|
<strong>{{ message.role === 'assistant' ? (message.assistantName || ui.ASSISTANT_DISPLAY_NAME) : '我' }}</strong>
|
||||||
|
<time>{{ message.time }}</time>
|
||||||
|
</header>
|
||||||
|
<div
|
||||||
|
v-if="message.text && message.role === 'assistant' && message.reviewPayload && ui.buildReviewMainMessageText(message)"
|
||||||
|
class="review-summary message-answer-content message-answer-markdown"
|
||||||
|
v-html="ui.renderMarkdown(ui.buildReviewMainMessageText(message))"
|
||||||
|
@click="ui.handleAssistantMarkdownClick($event, message)"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-else-if="message.text && message.role !== 'assistant'"
|
||||||
|
class="message-answer-content message-answer-markdown message-rich-text"
|
||||||
|
v-html="ui.renderMarkdown(message.text)"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-else-if="message.text && message.role === 'assistant'"
|
||||||
|
class="message-answer-content message-answer-markdown"
|
||||||
|
v-html="ui.renderMarkdown(message.text)"
|
||||||
|
@click="ui.handleAssistantMarkdownClick($event, message)"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="message.role === 'assistant' && message.applicationPreview"
|
||||||
|
class="application-preview-table"
|
||||||
|
role="table"
|
||||||
|
aria-label="申请信息核对表"
|
||||||
|
>
|
||||||
|
<div class="application-preview-row head" role="row">
|
||||||
|
<span role="columnheader">字段</span>
|
||||||
|
<span role="columnheader">内容</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="row in ui.resolveApplicationPreviewRows(message)"
|
||||||
|
:key="`${message.id}-${row.key}`"
|
||||||
|
class="application-preview-row"
|
||||||
|
:class="{
|
||||||
|
missing: row.missing,
|
||||||
|
editable: row.editable && !ui.submitting && !ui.reviewActionBusy && !ui.sessionSwitchBusy,
|
||||||
|
highlight: row.highlight
|
||||||
|
}"
|
||||||
|
role="row"
|
||||||
|
:tabindex="row.editable && !ui.submitting && !ui.reviewActionBusy && !ui.sessionSwitchBusy ? 0 : -1"
|
||||||
|
:aria-label="row.editable ? `编辑${row.label}` : row.label"
|
||||||
|
@click="row.editable && !ui.isApplicationPreviewEditing(message, row.key) && !ui.submitting && !ui.reviewActionBusy && !ui.sessionSwitchBusy && ui.openApplicationPreviewEditor(message, row.key, row.value)"
|
||||||
|
@keydown.enter.prevent="row.editable && !ui.isApplicationPreviewEditing(message, row.key) && !ui.submitting && !ui.reviewActionBusy && !ui.sessionSwitchBusy && ui.openApplicationPreviewEditor(message, row.key, row.value)"
|
||||||
|
@keydown.space.prevent="row.editable && !ui.isApplicationPreviewEditing(message, row.key) && !ui.submitting && !ui.reviewActionBusy && !ui.sessionSwitchBusy && ui.openApplicationPreviewEditor(message, row.key, row.value)"
|
||||||
|
>
|
||||||
|
<span class="application-preview-label" role="cell">{{ row.label }}</span>
|
||||||
|
<span class="application-preview-value" role="cell">
|
||||||
|
<input
|
||||||
|
v-if="ui.isApplicationPreviewEditing(message, row.key) && ui.resolveApplicationPreviewEditorControl(row.key) !== 'select'"
|
||||||
|
v-model="ui.applicationPreviewEditor.draftValue"
|
||||||
|
class="application-preview-input"
|
||||||
|
type="text"
|
||||||
|
autofocus
|
||||||
|
@click.stop
|
||||||
|
@keydown.stop="ui.handleApplicationPreviewEditorKeydown($event, message)"
|
||||||
|
@blur="ui.commitApplicationPreviewEditor(message)"
|
||||||
|
/>
|
||||||
|
<EnterpriseSelect
|
||||||
|
v-else-if="ui.isApplicationPreviewEditing(message, row.key)"
|
||||||
|
v-model="ui.applicationPreviewEditor.draftValue"
|
||||||
|
class="application-preview-input application-preview-select"
|
||||||
|
:options="ui.resolveApplicationPreviewEditorOptions(row.key)"
|
||||||
|
clearable
|
||||||
|
:teleported="false"
|
||||||
|
autofocus
|
||||||
|
@click.stop
|
||||||
|
@change="ui.commitApplicationPreviewEditor(message)"
|
||||||
|
@keydown.stop="ui.handleApplicationPreviewEditorKeydown($event, message)"
|
||||||
|
@blur="ui.commitApplicationPreviewEditor(message)"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<span class="application-preview-text">{{ row.value }}</span>
|
||||||
|
<button
|
||||||
|
v-if="row.editable"
|
||||||
|
type="button"
|
||||||
|
class="application-preview-edit-btn"
|
||||||
|
title="修改内容"
|
||||||
|
aria-label="修改内容"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy || ui.sessionSwitchBusy"
|
||||||
|
@click.stop="ui.openApplicationPreviewEditor(message, row.key, row.value)"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-pencil-outline"></i>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="message.role === 'assistant' && message.applicationPreview && ui.buildApplicationPreviewFooterText(message)"
|
||||||
|
class="application-preview-footer message-answer-content message-answer-markdown"
|
||||||
|
v-html="ui.renderMarkdown(ui.buildApplicationPreviewFooterText(message))"
|
||||||
|
@click="ui.handleAssistantMarkdownClick($event, message)"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="message.role === 'assistant' && message.welcomeQuickActions?.length"
|
||||||
|
class="welcome-quick-actions"
|
||||||
|
>
|
||||||
|
<p class="welcome-quick-actions-title">您可以对我进行以下操作:</p>
|
||||||
|
<div class="welcome-quick-action-grid">
|
||||||
|
<button
|
||||||
|
v-for="action in message.welcomeQuickActions"
|
||||||
|
:key="`${message.id}-${action.label}`"
|
||||||
|
type="button"
|
||||||
|
class="welcome-quick-action-btn"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy || ui.sessionSwitchBusy"
|
||||||
|
@click="ui.runWelcomeQuickAction(action)"
|
||||||
|
>
|
||||||
|
<i :class="action.icon"></i>
|
||||||
|
<span>{{ action.label }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="message.role === 'assistant' && !message.reviewPayload && !message.queryPayload && message.meta?.length" class="message-meta-row">
|
||||||
|
<span
|
||||||
|
v-for="item in message.meta"
|
||||||
|
:key="item"
|
||||||
|
class="message-meta-chip"
|
||||||
|
:class="message.metaTone"
|
||||||
|
>
|
||||||
|
{{ item }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="message.role === 'assistant' && !message.reviewPayload && !message.queryPayload && message.suggestedActions?.length"
|
||||||
|
class="message-suggested-actions"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
v-for="action in message.suggestedActions"
|
||||||
|
:key="`${message.id}-${action.action_type}-${action.label}`"
|
||||||
|
type="button"
|
||||||
|
class="message-suggested-action-btn"
|
||||||
|
:class="{
|
||||||
|
selected: ui.isSuggestedActionSelected(message, action),
|
||||||
|
locked: message.suggestedActionsLocked
|
||||||
|
}"
|
||||||
|
:disabled="message.suggestedActionsLocked || ui.submitting || ui.reviewActionBusy || ui.sessionSwitchBusy"
|
||||||
|
@click="ui.handleSuggestedAction(message, action)"
|
||||||
|
>
|
||||||
|
<span class="message-suggested-action-icon" aria-hidden="true">
|
||||||
|
<i :class="action.icon || 'mdi mdi-shape-outline'"></i>
|
||||||
|
</span>
|
||||||
|
<span class="message-suggested-action-copy">
|
||||||
|
<span class="message-suggested-action-title">{{ action.label }}</span>
|
||||||
|
<small v-if="action.description">{{ action.description }}</small>
|
||||||
|
</span>
|
||||||
|
<i class="message-suggested-action-arrow mdi mdi-arrow-right" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="message.role === 'assistant' && !message.reviewPayload && message.riskFlags?.length" class="message-detail-block">
|
||||||
|
<strong>风险标签</strong>
|
||||||
|
<div class="message-detail-chip-row">
|
||||||
|
<span v-for="item in message.riskFlags" :key="item" class="message-risk-chip">{{ item }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<details
|
||||||
|
v-if="message.role === 'assistant' && !message.reviewPayload && !message.queryPayload && message.citations?.length"
|
||||||
|
class="message-detail-block message-citation-disclosure"
|
||||||
|
>
|
||||||
|
<summary>
|
||||||
|
<strong>引用依据</strong>
|
||||||
|
<span>{{ message.citations.length }} 项</span>
|
||||||
|
<i class="mdi mdi-chevron-down"></i>
|
||||||
|
</summary>
|
||||||
|
<div class="message-citation-list">
|
||||||
|
<article v-for="item in message.citations" :key="`${message.id}-${item.code}`" class="message-citation-card">
|
||||||
|
<header>
|
||||||
|
<span>{{ item.title }}</span>
|
||||||
|
<small>{{ item.version || item.source_type }}</small>
|
||||||
|
</header>
|
||||||
|
<p>{{ item.excerpt || item.code }}</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="message.role === 'assistant' && !message.reviewPayload && message.queryPayload?.resultType === 'expense_claim_list'"
|
||||||
|
class="message-detail-block expense-query-block"
|
||||||
|
>
|
||||||
|
<strong>
|
||||||
|
{{ message.queryPayload.title || (message.queryPayload.selectionMode === 'draft_association' ? '选择关联草稿' : '最近 5 条筛选结果') }}
|
||||||
|
</strong>
|
||||||
|
|
||||||
|
<p v-if="ui.buildExpenseQueryWindowLabel(message.queryPayload)" class="expense-query-window-label">
|
||||||
|
{{ ui.buildExpenseQueryWindowLabel(message.queryPayload) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div v-if="message.queryPayload.statusGroups?.length" class="expense-query-summary-row">
|
||||||
|
<span
|
||||||
|
v-for="item in message.queryPayload.statusGroups"
|
||||||
|
:key="`${message.id}-${item.key}`"
|
||||||
|
class="expense-query-summary-chip"
|
||||||
|
:class="item.key"
|
||||||
|
>
|
||||||
|
{{ item.label }} {{ item.count }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="message.queryPayload.records?.length" class="expense-query-record-list compact">
|
||||||
|
<button
|
||||||
|
v-for="record in ui.getExpenseQueryVisibleRecords(message.queryPayload)"
|
||||||
|
:key="`${message.id}-${record.claimId}`"
|
||||||
|
type="button"
|
||||||
|
class="expense-query-record-card"
|
||||||
|
:class="{
|
||||||
|
selectable: message.queryPayload.selectionMode === 'draft_association',
|
||||||
|
selected: message.selectedQueryRecordId === record.claimId || message.queryPayload.selectedClaimId === record.claimId,
|
||||||
|
locked: message.querySelectionLocked || message.queryPayload.selectionLocked
|
||||||
|
}"
|
||||||
|
:disabled="message.queryPayload.selectionMode === 'draft_association' && (message.querySelectionLocked || message.queryPayload.selectionLocked)"
|
||||||
|
@click="ui.handleExpenseQueryRecordClick(message, record)"
|
||||||
|
>
|
||||||
|
<div class="expense-query-record-main">
|
||||||
|
<div class="expense-query-record-top">
|
||||||
|
<strong>{{ record.claimNo }}</strong>
|
||||||
|
<span class="expense-query-record-status" :class="record.statusGroup || 'other'">
|
||||||
|
{{ record.statusLabel }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p>{{ record.summary }}</p>
|
||||||
|
<div class="expense-query-record-meta">
|
||||||
|
<span>{{ record.expenseTypeLabel }}</span>
|
||||||
|
<span>{{ record.dateDisplay }}</span>
|
||||||
|
<span>{{ record.amountDisplay }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="record.riskItems?.length" class="expense-query-risk-row">
|
||||||
|
<button
|
||||||
|
v-for="risk in record.riskItems"
|
||||||
|
:key="`${message.id}-${record.claimId}-${risk.key}`"
|
||||||
|
type="button"
|
||||||
|
class="expense-query-risk-chip"
|
||||||
|
:class="risk.level"
|
||||||
|
@click.stop="ui.appendExpenseQueryRiskToConversation(record, risk)"
|
||||||
|
>
|
||||||
|
<span>{{ record.claimNo }}</span>
|
||||||
|
<strong>{{ risk.levelLabel }}</strong>
|
||||||
|
<em>{{ risk.title }}</em>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="ui.getExpenseQueryTotalPages(message.queryPayload) > 1"
|
||||||
|
class="expense-query-pager"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="expense-query-pager-btn"
|
||||||
|
:disabled="ui.getExpenseQueryActivePage(message.queryPayload) === 1"
|
||||||
|
aria-label="上一页"
|
||||||
|
@click="ui.shiftExpenseQueryPage(message, -1)"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-chevron-left"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="expense-query-pager-dots" aria-label="单据分页">
|
||||||
|
<button
|
||||||
|
v-for="page in ui.getExpenseQueryTotalPages(message.queryPayload)"
|
||||||
|
:key="`${message.id}-query-page-${page}`"
|
||||||
|
type="button"
|
||||||
|
class="expense-query-pager-dot"
|
||||||
|
:class="{ active: ui.getExpenseQueryActivePage(message.queryPayload) === page }"
|
||||||
|
:aria-label="`第 ${page} 页`"
|
||||||
|
@click="ui.setExpenseQueryPage(message, page)"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="expense-query-pager-btn"
|
||||||
|
:disabled="ui.getExpenseQueryActivePage(message.queryPayload) === ui.getExpenseQueryTotalPages(message.queryPayload)"
|
||||||
|
aria-label="下一页"
|
||||||
|
@click="ui.shiftExpenseQueryPage(message, 1)"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="expense-query-empty">
|
||||||
|
<i class="mdi mdi-file-search-outline"></i>
|
||||||
|
<span>{{ message.queryPayload.emptyText || '当前没有可直接展开的近期待办单据。' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
v-if="ui.buildExpenseQueryHint(message.queryPayload)"
|
||||||
|
class="expense-query-hint message-answer-markdown"
|
||||||
|
v-html="ui.renderMarkdown(ui.buildExpenseQueryHint(message.queryPayload))"
|
||||||
|
@click="ui.handleAssistantMarkdownClick($event, message)"
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="message.role === 'assistant' && message.reviewPayload" class="message-detail-block review-message-block">
|
||||||
|
<div class="review-plain-followup">
|
||||||
|
<template
|
||||||
|
v-for="followup in [ui.buildReviewPlainFollowupForMessage(message)]"
|
||||||
|
:key="`${message.id}-review-followup`"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
class="review-plain-lead"
|
||||||
|
:class="{ danger: followup.tone === 'danger' }"
|
||||||
|
>
|
||||||
|
{{ followup.lead }}
|
||||||
|
</h3>
|
||||||
|
<p v-if="followup.summary" class="review-plain-summary">
|
||||||
|
{{ followup.summary }}
|
||||||
|
</p>
|
||||||
|
<ul v-if="followup.items.length" class="review-plain-list">
|
||||||
|
<li
|
||||||
|
v-for="item in followup.items"
|
||||||
|
:key="`${message.id}-${item.key}`"
|
||||||
|
>
|
||||||
|
<span class="review-plain-label">{{ item.label }}:</span>
|
||||||
|
<span>{{ item.text }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p
|
||||||
|
v-for="line in followup.notes"
|
||||||
|
:key="`${message.id}-note-${line}`"
|
||||||
|
class="review-plain-note"
|
||||||
|
>
|
||||||
|
{{ line }}
|
||||||
|
</p>
|
||||||
|
<p v-if="ui.canUseInlineSaveDraft(message)" class="review-inline-save-copy">
|
||||||
|
请核查上面的关键信息。您也可以暂时不处理上述的这些内容,我可以帮你先保存为
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="review-inline-draft-link"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy || ui.sessionSwitchBusy"
|
||||||
|
@click="ui.handleInlineSaveDraft(message)"
|
||||||
|
>
|
||||||
|
草稿
|
||||||
|
</button>
|
||||||
|
。
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="ui.buildReviewNextStepRichCopyForMessage(message)"
|
||||||
|
class="review-next-step-rich-copy message-answer-markdown"
|
||||||
|
v-html="ui.renderMarkdown(ui.buildReviewNextStepRichCopyForMessage(message))"
|
||||||
|
@click="ui.handleAssistantMarkdownClick($event, message)"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="ui.resolveReviewFooterActions(message.reviewPayload).length"
|
||||||
|
class="review-footer-actions"
|
||||||
|
>
|
||||||
|
<div class="review-footer-btn-row">
|
||||||
|
<button
|
||||||
|
v-for="action in ui.resolveReviewFooterActions(message.reviewPayload)"
|
||||||
|
:key="`${message.id}-${action.action_type}`"
|
||||||
|
type="button"
|
||||||
|
:class="['review-footer-btn', action.emphasis === 'primary' ? 'primary' : '']"
|
||||||
|
:disabled="ui.submitting || ui.reviewActionBusy || ui.sessionSwitchBusy"
|
||||||
|
@click="ui.handleReviewAction(message, action)"
|
||||||
|
>
|
||||||
|
{{ action.label || ui.buildReviewPrimaryButtonLabel(message.reviewPayload, message.draftPayload) }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="message.role === 'assistant' && !message.reviewPayload && message.draftPayload" class="draft-preview">
|
||||||
|
<header>
|
||||||
|
<strong>{{ message.draftPayload.title }}</strong>
|
||||||
|
<span>待人工确认</span>
|
||||||
|
</header>
|
||||||
|
<pre>{{ message.draftPayload.body }}</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="message.attachments?.length" class="message-files">
|
||||||
|
<span v-for="file in message.attachments" :key="file" class="file-chip">
|
||||||
|
<i class="mdi mdi-paperclip"></i>
|
||||||
|
{{ file }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import EnterpriseSelect from '../shared/EnterpriseSelect.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TravelReimbursementMessageItem',
|
||||||
|
components: {
|
||||||
|
EnterpriseSelect
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
message: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
ui: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped src="../../assets/styles/components/travel-reimbursement-message-item.css"></style>
|
||||||
62
web/src/components/travel/TravelRequestApprovalDialog.vue
Normal file
62
web/src/components/travel/TravelRequestApprovalDialog.vue
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<template>
|
||||||
|
<ConfirmDialog
|
||||||
|
:open="open"
|
||||||
|
:badge="badge"
|
||||||
|
badge-tone="info"
|
||||||
|
:title="title"
|
||||||
|
:description="description"
|
||||||
|
cancel-text="返回核对"
|
||||||
|
:confirm-text="confirmText"
|
||||||
|
:busy-text="busyText"
|
||||||
|
confirm-tone="primary"
|
||||||
|
confirm-icon="mdi mdi-check-circle-outline"
|
||||||
|
:busy="busy"
|
||||||
|
@close="emit('close')"
|
||||||
|
@confirm="emit('confirm')"
|
||||||
|
>
|
||||||
|
<div class="submit-confirm-summary" aria-label="领导审批通过摘要">
|
||||||
|
<div class="submit-confirm-row">
|
||||||
|
<span>单据编号</span>
|
||||||
|
<strong>{{ documentNo }}</strong>
|
||||||
|
</div>
|
||||||
|
<div class="submit-confirm-row">
|
||||||
|
<span>当前节点</span>
|
||||||
|
<strong>{{ node }}</strong>
|
||||||
|
</div>
|
||||||
|
<div class="submit-confirm-row">
|
||||||
|
<span>{{ summaryLabel }}</span>
|
||||||
|
<strong>{{ nextStage }}</strong>
|
||||||
|
</div>
|
||||||
|
<div class="submit-confirm-row">
|
||||||
|
<span>{{ opinionTitle }}</span>
|
||||||
|
<strong>{{ normalizedOpinion }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ConfirmDialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
import ConfirmDialog from '../shared/ConfirmDialog.vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
open: { type: Boolean, required: true },
|
||||||
|
badge: { type: String, required: true },
|
||||||
|
title: { type: String, required: true },
|
||||||
|
description: { type: String, required: true },
|
||||||
|
confirmText: { type: String, required: true },
|
||||||
|
busyText: { type: String, required: true },
|
||||||
|
busy: { type: Boolean, required: true },
|
||||||
|
documentNo: { type: [String, Number], required: true },
|
||||||
|
node: { type: String, default: '' },
|
||||||
|
summaryLabel: { type: String, required: true },
|
||||||
|
nextStage: { type: String, required: true },
|
||||||
|
opinionTitle: { type: String, required: true },
|
||||||
|
opinion: { type: String, default: '' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['close', 'confirm'])
|
||||||
|
|
||||||
|
const normalizedOpinion = computed(() => props.opinion.trim() || '未填写')
|
||||||
|
</script>
|
||||||
31
web/src/components/travel/TravelRequestDeleteDialog.vue
Normal file
31
web/src/components/travel/TravelRequestDeleteDialog.vue
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<ConfirmDialog
|
||||||
|
:open="open"
|
||||||
|
:badge="badge"
|
||||||
|
badge-tone="danger"
|
||||||
|
:title="title"
|
||||||
|
:description="description"
|
||||||
|
cancel-text="取消"
|
||||||
|
confirm-text="确认删除"
|
||||||
|
busy-text="删除中..."
|
||||||
|
confirm-tone="danger"
|
||||||
|
confirm-icon="mdi mdi-trash-can-outline"
|
||||||
|
:busy="busy"
|
||||||
|
@close="emit('close')"
|
||||||
|
@confirm="emit('confirm')"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import ConfirmDialog from '../shared/ConfirmDialog.vue'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
open: { type: Boolean, required: true },
|
||||||
|
badge: { type: String, required: true },
|
||||||
|
title: { type: String, required: true },
|
||||||
|
description: { type: String, required: true },
|
||||||
|
busy: { type: Boolean, required: true }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['close', 'confirm'])
|
||||||
|
</script>
|
||||||
23
web/src/components/travel/TravelRequestReturnDialog.vue
Normal file
23
web/src/components/travel/TravelRequestReturnDialog.vue
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<ReturnReasonDialog
|
||||||
|
:open="open"
|
||||||
|
:title="title"
|
||||||
|
:description="description"
|
||||||
|
:busy="busy"
|
||||||
|
@close="emit('close')"
|
||||||
|
@confirm="emit('confirm', $event)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import ReturnReasonDialog from '../shared/ReturnReasonDialog.vue'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
open: { type: Boolean, required: true },
|
||||||
|
title: { type: String, required: true },
|
||||||
|
description: { type: String, required: true },
|
||||||
|
busy: { type: Boolean, required: true }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['close', 'confirm'])
|
||||||
|
</script>
|
||||||
@@ -25,11 +25,11 @@ export function useOverviewView() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const demoDepartments = [
|
const demoDepartments = [
|
||||||
{ name: '销售部', amount: 182000, color: '#10b981' },
|
{ name: '销售部', amount: 182000, color: 'var(--theme-primary)' },
|
||||||
{ name: '研发中心', amount: 146000, color: '#3b82f6' },
|
{ name: '研发中心', amount: 146000, color: 'var(--chart-blue)' },
|
||||||
{ name: '市场部', amount: 96000, color: '#f59e0b' },
|
{ name: '市场部', amount: 96000, color: 'var(--chart-amber)' },
|
||||||
{ name: '运营部', amount: 68600, color: '#8b5cf6' },
|
{ name: '运营部', amount: 68600, color: 'var(--chart-purple)' },
|
||||||
{ name: '行政部', amount: 48300, color: '#3b82f6' }
|
{ name: '行政部', amount: 48300, color: 'var(--chart-blue)' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const formatCompact = (value) => {
|
const formatCompact = (value) => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
|
|
||||||
import { useSystemState } from './useSystemState.js'
|
import { useSystemState } from './useSystemState.js'
|
||||||
|
import { useThemeSkin } from './useThemeSkin.js'
|
||||||
import { fetchSettings, saveSettings } from '../services/settings.js'
|
import { fetchSettings, saveSettings } from '../services/settings.js'
|
||||||
import { useToast } from './useToast.js'
|
import { useToast } from './useToast.js'
|
||||||
import {
|
import {
|
||||||
@@ -28,6 +29,12 @@ import {
|
|||||||
export function useSettings() {
|
export function useSettings() {
|
||||||
const { toast } = useToast()
|
const { toast } = useToast()
|
||||||
const { companyProfile, currentUser, updateCompanyProfilePreview } = useSystemState()
|
const { companyProfile, currentUser, updateCompanyProfilePreview } = useSystemState()
|
||||||
|
const {
|
||||||
|
activeThemeSkin,
|
||||||
|
activeThemeSkinId,
|
||||||
|
setThemeSkin,
|
||||||
|
themeSkinOptions
|
||||||
|
} = useThemeSkin()
|
||||||
|
|
||||||
const buildResolvedDefaults = () => buildDefaultState(companyProfile.value, currentUser.value)
|
const buildResolvedDefaults = () => buildDefaultState(companyProfile.value, currentUser.value)
|
||||||
const pageState = ref(mergeState(buildResolvedDefaults(), readStoredSettings()))
|
const pageState = ref(mergeState(buildResolvedDefaults(), readStoredSettings()))
|
||||||
@@ -40,6 +47,11 @@ export function useSettings() {
|
|||||||
const logLevels = LOG_LEVELS
|
const logLevels = LOG_LEVELS
|
||||||
const providerOptions = PROVIDER_OPTIONS
|
const providerOptions = PROVIDER_OPTIONS
|
||||||
const sessionRetentionOptions = SESSION_RETENTION_OPTIONS
|
const sessionRetentionOptions = SESSION_RETENTION_OPTIONS
|
||||||
|
const archiveCycleOptions = [
|
||||||
|
{ label: '按天归档', value: 'daily' },
|
||||||
|
{ label: '按周归档', value: 'weekly' },
|
||||||
|
{ label: '按月归档', value: 'monthly' }
|
||||||
|
]
|
||||||
|
|
||||||
const sectionStatus = computed(() => computeSectionStatus(pageState.value))
|
const sectionStatus = computed(() => computeSectionStatus(pageState.value))
|
||||||
const completedSectionCount = computed(() => Object.values(sectionStatus.value).filter(Boolean).length)
|
const completedSectionCount = computed(() => Object.values(sectionStatus.value).filter(Boolean).length)
|
||||||
@@ -293,6 +305,14 @@ export function useSettings() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectThemeSkin(skinId) {
|
||||||
|
setThemeSkin(skinId)
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveAppearanceSection() {
|
||||||
|
toast('界面皮肤已应用到当前浏览器。')
|
||||||
|
}
|
||||||
|
|
||||||
async function saveLlmSection() {
|
async function saveLlmSection() {
|
||||||
const llmForm = pageState.value.llmForm
|
const llmForm = pageState.value.llmForm
|
||||||
const modelConfigs = [
|
const modelConfigs = [
|
||||||
@@ -391,6 +411,11 @@ export function useSettings() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (activeSection.value === 'appearance') {
|
||||||
|
saveAppearanceSection()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (activeSection.value === 'session') {
|
if (activeSection.value === 'session') {
|
||||||
await saveSessionSection()
|
await saveSessionSection()
|
||||||
return
|
return
|
||||||
@@ -460,6 +485,9 @@ export function useSettings() {
|
|||||||
return {
|
return {
|
||||||
activeSection,
|
activeSection,
|
||||||
activeSectionConfig,
|
activeSectionConfig,
|
||||||
|
activeThemeSkin,
|
||||||
|
activeThemeSkinId,
|
||||||
|
archiveCycleOptions,
|
||||||
activateSection,
|
activateSection,
|
||||||
clearRenderSecretMask,
|
clearRenderSecretMask,
|
||||||
completedSectionCount,
|
completedSectionCount,
|
||||||
@@ -473,7 +501,9 @@ export function useSettings() {
|
|||||||
saveActiveSection,
|
saveActiveSection,
|
||||||
sectionStatus,
|
sectionStatus,
|
||||||
sections,
|
sections,
|
||||||
|
selectThemeSkin,
|
||||||
selectSessionRetentionDays,
|
selectSessionRetentionDays,
|
||||||
|
themeSkinOptions,
|
||||||
toggleSessionRetentionPicker,
|
toggleSessionRetentionPicker,
|
||||||
closeSessionRetentionPicker,
|
closeSessionRetentionPicker,
|
||||||
toggleBoolean,
|
toggleBoolean,
|
||||||
|
|||||||
64
web/src/composables/useThemeColors.js
Normal file
64
web/src/composables/useThemeColors.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
import { useThemeSkin } from './useThemeSkin.js'
|
||||||
|
|
||||||
|
const DEFAULT_COLORS = {
|
||||||
|
primary: '#3a7ca5',
|
||||||
|
primaryActive: '#255b7d',
|
||||||
|
primarySoft: '#eaf4fa',
|
||||||
|
success: '#2f855a',
|
||||||
|
warning: '#b7791f',
|
||||||
|
danger: '#ef4444',
|
||||||
|
info: '#475569',
|
||||||
|
chartBlue: '#4f6f9f',
|
||||||
|
chartPurple: '#6e7fa6',
|
||||||
|
chartAmber: '#b58b4c'
|
||||||
|
}
|
||||||
|
|
||||||
|
function readCssVariable(name, fallback) {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = window.getComputedStyle(document.documentElement).getPropertyValue(name).trim()
|
||||||
|
return value || fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveCssColor(value, fallback = DEFAULT_COLORS.primary) {
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
const cssVariableMatch = value.match(/^var\((--[^,\s)]+)(?:,\s*([^)]+))?\)$/)
|
||||||
|
if (!cssVariableMatch) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
return readCssVariable(cssVariableMatch[1], cssVariableMatch[2]?.trim() || fallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useThemeColors() {
|
||||||
|
const { activeThemeSkinId } = useThemeSkin()
|
||||||
|
|
||||||
|
return computed(() => {
|
||||||
|
activeThemeSkinId.value
|
||||||
|
|
||||||
|
const primary = readCssVariable('--theme-primary', DEFAULT_COLORS.primary)
|
||||||
|
const primaryActive = readCssVariable('--theme-primary-active', DEFAULT_COLORS.primaryActive)
|
||||||
|
|
||||||
|
return {
|
||||||
|
primary,
|
||||||
|
primaryActive,
|
||||||
|
primarySoft: readCssVariable('--theme-primary-soft', DEFAULT_COLORS.primarySoft),
|
||||||
|
success: readCssVariable('--success', DEFAULT_COLORS.success),
|
||||||
|
warning: readCssVariable('--warning', DEFAULT_COLORS.warning),
|
||||||
|
danger: readCssVariable('--danger', DEFAULT_COLORS.danger),
|
||||||
|
info: readCssVariable('--info', DEFAULT_COLORS.info),
|
||||||
|
chartPrimary: resolveCssColor(readCssVariable('--chart-primary', primary), primary),
|
||||||
|
chartBlue: resolveCssColor(readCssVariable('--chart-blue', DEFAULT_COLORS.chartBlue), DEFAULT_COLORS.chartBlue),
|
||||||
|
chartPurple: resolveCssColor(readCssVariable('--chart-purple', DEFAULT_COLORS.chartPurple), DEFAULT_COLORS.chartPurple),
|
||||||
|
chartAmber: resolveCssColor(readCssVariable('--chart-amber', DEFAULT_COLORS.chartAmber), DEFAULT_COLORS.chartAmber),
|
||||||
|
chartDanger: resolveCssColor(readCssVariable('--chart-danger', DEFAULT_COLORS.danger), DEFAULT_COLORS.danger)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
282
web/src/composables/useThemeSkin.js
Normal file
282
web/src/composables/useThemeSkin.js
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
|
const THEME_SKIN_STORAGE_KEY = 'x-financial-theme-skin'
|
||||||
|
const DEFAULT_THEME_SKIN_ID = 'sky'
|
||||||
|
|
||||||
|
const DEFAULT_SEMANTIC_COLORS = {
|
||||||
|
success: '#2f855a',
|
||||||
|
successHover: '#276749',
|
||||||
|
successActive: '#22543d',
|
||||||
|
successSoft: '#f0f7f2',
|
||||||
|
successLine: '#cde6d5',
|
||||||
|
warning: '#b7791f',
|
||||||
|
warningHover: '#975a16',
|
||||||
|
warningActive: '#7b4514',
|
||||||
|
warningSoft: '#fff8eb',
|
||||||
|
warningLine: '#efd9af',
|
||||||
|
danger: '#dc2626',
|
||||||
|
dangerHover: '#b91c1c',
|
||||||
|
dangerActive: '#991b1b',
|
||||||
|
dangerSoft: '#fef2f2',
|
||||||
|
dangerLine: '#fecaca',
|
||||||
|
info: '#475569',
|
||||||
|
infoHover: '#334155',
|
||||||
|
infoActive: '#1e293b',
|
||||||
|
infoSoft: '#f1f5f9',
|
||||||
|
infoLine: '#cbd5e1'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const THEME_SKIN_OPTIONS = [
|
||||||
|
{
|
||||||
|
id: 'sky',
|
||||||
|
label: '浅蓝企业',
|
||||||
|
desc: '默认皮肤,降低蓝色饱和度,适合财务 SaaS 和审批后台。',
|
||||||
|
primary: '#3a7ca5',
|
||||||
|
primaryHover: '#2f6d95',
|
||||||
|
primaryActive: '#255b7d',
|
||||||
|
primarySoft: '#eaf4fa',
|
||||||
|
primarySoftStrong: '#d4e8f3',
|
||||||
|
secondary: '#4f6f9f',
|
||||||
|
chartBlue: '#4f6f9f',
|
||||||
|
chartPurple: '#6e7fa6',
|
||||||
|
chartAmber: '#b58b4c'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'blue',
|
||||||
|
label: '湖蓝灰',
|
||||||
|
desc: '偏灰的湖蓝色,弱化科技感,更适合高密度运营页面。',
|
||||||
|
primary: '#477c9e',
|
||||||
|
primaryHover: '#3a6a89',
|
||||||
|
primaryActive: '#305873',
|
||||||
|
primarySoft: '#edf5f8',
|
||||||
|
primarySoftStrong: '#d8e8ef',
|
||||||
|
secondary: '#5d7288',
|
||||||
|
chartBlue: '#477c9e',
|
||||||
|
chartPurple: '#77799c',
|
||||||
|
chartAmber: '#b28a54'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'navy',
|
||||||
|
label: '稳健蓝',
|
||||||
|
desc: '偏金融和管理驾驶舱的稳重蓝,适合长时间办公查看。',
|
||||||
|
primary: '#4b6f95',
|
||||||
|
primaryHover: '#405f80',
|
||||||
|
primaryActive: '#354e69',
|
||||||
|
primarySoft: '#eef3f8',
|
||||||
|
primarySoftStrong: '#dbe6f0',
|
||||||
|
secondary: '#6b7280',
|
||||||
|
chartBlue: '#4b6f95',
|
||||||
|
chartPurple: '#69769d',
|
||||||
|
chartAmber: '#aa8a55'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'teal',
|
||||||
|
label: '雾青',
|
||||||
|
desc: '保留绿色倾向但降低鲜艳度,比旧绿色更克制。',
|
||||||
|
primary: '#3f827c',
|
||||||
|
primaryHover: '#36706b',
|
||||||
|
primaryActive: '#2d5c58',
|
||||||
|
primarySoft: '#eef8f6',
|
||||||
|
primarySoftStrong: '#d8ebe8',
|
||||||
|
secondary: '#4f6f9f',
|
||||||
|
chartBlue: '#4f7f9f',
|
||||||
|
chartPurple: '#708099',
|
||||||
|
chartAmber: '#b18a53'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'legacy-green',
|
||||||
|
label: '经典绿',
|
||||||
|
desc: '保留旧版系统绿色,适合继续沿用原有品牌记忆。',
|
||||||
|
primary: '#10b981',
|
||||||
|
primaryHover: '#059669',
|
||||||
|
primaryActive: '#047857',
|
||||||
|
primarySoft: '#ecfdf5',
|
||||||
|
primarySoftStrong: '#d1fae5',
|
||||||
|
secondary: '#2563eb',
|
||||||
|
chartBlue: '#2563eb',
|
||||||
|
chartPurple: '#6d6a9f',
|
||||||
|
chartAmber: '#b88a44'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sage',
|
||||||
|
label: '鼠尾草绿',
|
||||||
|
desc: '低饱和灰绿色,比经典绿更安静,适合企业内控场景。',
|
||||||
|
primary: '#5f8d72',
|
||||||
|
primaryHover: '#517b62',
|
||||||
|
primaryActive: '#436653',
|
||||||
|
primarySoft: '#f0f7f2',
|
||||||
|
primarySoftStrong: '#dcebe0',
|
||||||
|
secondary: '#4f6f9f',
|
||||||
|
chartBlue: '#4f748f',
|
||||||
|
chartPurple: '#7a7898',
|
||||||
|
chartAmber: '#a98753'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'slate',
|
||||||
|
label: '石板灰蓝',
|
||||||
|
desc: '弱主色方案,适合审计、规则和报表密集页面。',
|
||||||
|
primary: '#64748b',
|
||||||
|
primaryHover: '#526174',
|
||||||
|
primaryActive: '#3f4a5a',
|
||||||
|
primarySoft: '#f1f5f9',
|
||||||
|
primarySoftStrong: '#e2e8f0',
|
||||||
|
secondary: '#3a7ca5',
|
||||||
|
chartBlue: '#5d7590',
|
||||||
|
chartPurple: '#77748f',
|
||||||
|
chartAmber: '#a88955'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'soft-violet',
|
||||||
|
label: '灰紫蓝',
|
||||||
|
desc: '保留一点智能系统气质,但用灰度压低 AI 感和饱和度。',
|
||||||
|
primary: '#6d6a9f',
|
||||||
|
primaryHover: '#5f5b8c',
|
||||||
|
primaryActive: '#504c78',
|
||||||
|
primarySoft: '#f2f1f8',
|
||||||
|
primarySoftStrong: '#e2e0ef',
|
||||||
|
secondary: '#477c9e',
|
||||||
|
chartBlue: '#4f7495',
|
||||||
|
chartPurple: '#6d6a9f',
|
||||||
|
chartAmber: '#a98857'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const activeThemeSkinId = ref(DEFAULT_THEME_SKIN_ID)
|
||||||
|
|
||||||
|
function findThemeSkin(id) {
|
||||||
|
return THEME_SKIN_OPTIONS.find((skin) => skin.id === id) || THEME_SKIN_OPTIONS[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
function hexToRgb(hex) {
|
||||||
|
const normalized = String(hex || '').replace('#', '')
|
||||||
|
const value = normalized.length === 3
|
||||||
|
? normalized.split('').map((item) => item + item).join('')
|
||||||
|
: normalized
|
||||||
|
const numberValue = Number.parseInt(value, 16)
|
||||||
|
|
||||||
|
if (!Number.isFinite(numberValue) || value.length !== 6) {
|
||||||
|
return '58, 124, 165'
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
(numberValue >> 16) & 255,
|
||||||
|
(numberValue >> 8) & 255,
|
||||||
|
numberValue & 255
|
||||||
|
].join(', ')
|
||||||
|
}
|
||||||
|
|
||||||
|
function setVariables(root, variables) {
|
||||||
|
Object.entries(variables).forEach(([key, value]) => {
|
||||||
|
root.style.setProperty(key, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyThemeSkin(skin) {
|
||||||
|
if (typeof document === 'undefined') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = document.documentElement
|
||||||
|
const primaryRgb = hexToRgb(skin.primary)
|
||||||
|
const secondaryRgb = hexToRgb(skin.secondary)
|
||||||
|
const successRgb = hexToRgb(DEFAULT_SEMANTIC_COLORS.success)
|
||||||
|
const warningRgb = hexToRgb(DEFAULT_SEMANTIC_COLORS.warning)
|
||||||
|
const dangerRgb = hexToRgb(DEFAULT_SEMANTIC_COLORS.danger)
|
||||||
|
const infoRgb = hexToRgb(DEFAULT_SEMANTIC_COLORS.info)
|
||||||
|
|
||||||
|
root.dataset.themeSkin = skin.id
|
||||||
|
|
||||||
|
setVariables(root, {
|
||||||
|
'--primary': skin.primary,
|
||||||
|
'--primary-hover': skin.primaryHover,
|
||||||
|
'--primary-active': skin.primaryActive,
|
||||||
|
'--primary-soft': skin.primarySoft,
|
||||||
|
'--primary-soft-strong': skin.primarySoftStrong,
|
||||||
|
'--primary-rgb': primaryRgb,
|
||||||
|
'--secondary': skin.secondary,
|
||||||
|
'--secondary-rgb': secondaryRgb,
|
||||||
|
'--theme-secondary': skin.secondary,
|
||||||
|
'--theme-secondary-rgb': secondaryRgb,
|
||||||
|
'--theme-primary': skin.primary,
|
||||||
|
'--theme-primary-hover': skin.primaryHover,
|
||||||
|
'--theme-primary-active': skin.primaryActive,
|
||||||
|
'--theme-primary-soft': skin.primarySoft,
|
||||||
|
'--theme-primary-soft-strong': skin.primarySoftStrong,
|
||||||
|
'--theme-primary-light-5': 'color-mix(in srgb, var(--theme-primary) 46%, white)',
|
||||||
|
'--theme-primary-light-9': 'color-mix(in srgb, var(--theme-primary) 8%, white)',
|
||||||
|
'--theme-primary-rgb': primaryRgb,
|
||||||
|
'--theme-primary-shadow': `rgba(${primaryRgb}, 0.16)`,
|
||||||
|
'--theme-focus-ring': `rgba(${primaryRgb}, 0.12)`,
|
||||||
|
'--theme-gradient-primary': `linear-gradient(135deg, ${skin.primary}, ${skin.primaryActive})`,
|
||||||
|
'--chart-primary': skin.primary,
|
||||||
|
'--chart-primary-rgb': primaryRgb,
|
||||||
|
'--chart-blue': skin.chartBlue,
|
||||||
|
'--chart-purple': skin.chartPurple,
|
||||||
|
'--chart-amber': skin.chartAmber,
|
||||||
|
'--success': DEFAULT_SEMANTIC_COLORS.success,
|
||||||
|
'--success-hover': DEFAULT_SEMANTIC_COLORS.successHover,
|
||||||
|
'--success-active': DEFAULT_SEMANTIC_COLORS.successActive,
|
||||||
|
'--success-soft': DEFAULT_SEMANTIC_COLORS.successSoft,
|
||||||
|
'--success-line': DEFAULT_SEMANTIC_COLORS.successLine,
|
||||||
|
'--success-rgb': successRgb,
|
||||||
|
'--warning': DEFAULT_SEMANTIC_COLORS.warning,
|
||||||
|
'--warning-hover': DEFAULT_SEMANTIC_COLORS.warningHover,
|
||||||
|
'--warning-active': DEFAULT_SEMANTIC_COLORS.warningActive,
|
||||||
|
'--warning-soft': DEFAULT_SEMANTIC_COLORS.warningSoft,
|
||||||
|
'--warning-line': DEFAULT_SEMANTIC_COLORS.warningLine,
|
||||||
|
'--warning-rgb': warningRgb,
|
||||||
|
'--danger': DEFAULT_SEMANTIC_COLORS.danger,
|
||||||
|
'--danger-hover': DEFAULT_SEMANTIC_COLORS.dangerHover,
|
||||||
|
'--danger-active': DEFAULT_SEMANTIC_COLORS.dangerActive,
|
||||||
|
'--danger-soft': DEFAULT_SEMANTIC_COLORS.dangerSoft,
|
||||||
|
'--danger-line': DEFAULT_SEMANTIC_COLORS.dangerLine,
|
||||||
|
'--danger-rgb': dangerRgb,
|
||||||
|
'--info': DEFAULT_SEMANTIC_COLORS.info,
|
||||||
|
'--info-hover': DEFAULT_SEMANTIC_COLORS.infoHover,
|
||||||
|
'--info-active': DEFAULT_SEMANTIC_COLORS.infoActive,
|
||||||
|
'--info-soft': DEFAULT_SEMANTIC_COLORS.infoSoft,
|
||||||
|
'--info-line': DEFAULT_SEMANTIC_COLORS.infoLine,
|
||||||
|
'--info-rgb': infoRgb,
|
||||||
|
'--el-color-primary': skin.primary,
|
||||||
|
'--el-color-primary-dark-2': skin.primaryActive,
|
||||||
|
'--el-color-primary-light-3': skin.primaryHover,
|
||||||
|
'--el-color-primary-light-5': 'var(--theme-primary-light-5)',
|
||||||
|
'--el-color-primary-light-7': skin.primarySoftStrong,
|
||||||
|
'--el-color-primary-light-8': skin.primarySoft,
|
||||||
|
'--el-color-primary-light-9': 'var(--theme-primary-light-9)'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function readStoredThemeSkinId() {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return DEFAULT_THEME_SKIN_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
const stored = window.localStorage.getItem(THEME_SKIN_STORAGE_KEY)
|
||||||
|
return findThemeSkin(stored).id
|
||||||
|
}
|
||||||
|
|
||||||
|
export function installThemeSkin() {
|
||||||
|
const skin = findThemeSkin(readStoredThemeSkinId())
|
||||||
|
activeThemeSkinId.value = skin.id
|
||||||
|
applyThemeSkin(skin)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setThemeSkin(id) {
|
||||||
|
const skin = findThemeSkin(id)
|
||||||
|
activeThemeSkinId.value = skin.id
|
||||||
|
applyThemeSkin(skin)
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.localStorage.setItem(THEME_SKIN_STORAGE_KEY, skin.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useThemeSkin() {
|
||||||
|
return {
|
||||||
|
activeThemeSkin: computed(() => findThemeSkin(activeThemeSkinId.value)),
|
||||||
|
activeThemeSkinId,
|
||||||
|
setThemeSkin,
|
||||||
|
themeSkinOptions: THEME_SKIN_OPTIONS
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ export const metricBlueprints = [
|
|||||||
key: 'pendingCount',
|
key: 'pendingCount',
|
||||||
label: '待审批单据',
|
label: '待审批单据',
|
||||||
unit: '单',
|
unit: '单',
|
||||||
accent: '#10b981',
|
accent: 'var(--theme-primary)',
|
||||||
icon: 'mdi mdi-file-document-outline',
|
icon: 'mdi mdi-file-document-outline',
|
||||||
trend: 'down',
|
trend: 'down',
|
||||||
change: '12.5%',
|
change: '12.5%',
|
||||||
@@ -12,7 +12,7 @@ export const metricBlueprints = [
|
|||||||
{
|
{
|
||||||
key: 'pendingAmount',
|
key: 'pendingAmount',
|
||||||
label: '待处理金额',
|
label: '待处理金额',
|
||||||
accent: '#3b82f6',
|
accent: 'var(--chart-blue)',
|
||||||
icon: 'mdi mdi-wallet',
|
icon: 'mdi mdi-wallet',
|
||||||
trend: 'up',
|
trend: 'up',
|
||||||
change: '8.3%',
|
change: '8.3%',
|
||||||
@@ -22,7 +22,7 @@ export const metricBlueprints = [
|
|||||||
key: 'avgSla',
|
key: 'avgSla',
|
||||||
label: '平均审批时长',
|
label: '平均审批时长',
|
||||||
unit: 'h',
|
unit: 'h',
|
||||||
accent: '#8b5cf6',
|
accent: 'var(--chart-purple)',
|
||||||
icon: 'mdi mdi-clock-outline',
|
icon: 'mdi mdi-clock-outline',
|
||||||
trend: 'down',
|
trend: 'down',
|
||||||
change: '14.8%',
|
change: '14.8%',
|
||||||
@@ -32,7 +32,7 @@ export const metricBlueprints = [
|
|||||||
key: 'autoPassRate',
|
key: 'autoPassRate',
|
||||||
label: '自动审单通过率',
|
label: '自动审单通过率',
|
||||||
unit: '%',
|
unit: '%',
|
||||||
accent: '#16a34a',
|
accent: 'var(--success)',
|
||||||
icon: 'mdi mdi-shield-outline',
|
icon: 'mdi mdi-shield-outline',
|
||||||
trend: 'up',
|
trend: 'up',
|
||||||
change: '6.2%',
|
change: '6.2%',
|
||||||
@@ -42,7 +42,7 @@ export const metricBlueprints = [
|
|||||||
key: 'riskCount',
|
key: 'riskCount',
|
||||||
label: '异常预警单',
|
label: '异常预警单',
|
||||||
unit: '单',
|
unit: '单',
|
||||||
accent: '#ef4444',
|
accent: 'var(--danger)',
|
||||||
icon: 'mdi mdi-alert',
|
icon: 'mdi mdi-alert',
|
||||||
trend: 'up',
|
trend: 'up',
|
||||||
change: '16.7%',
|
change: '16.7%',
|
||||||
@@ -52,7 +52,7 @@ export const metricBlueprints = [
|
|||||||
key: 'slaRate',
|
key: 'slaRate',
|
||||||
label: 'SLA 达成率',
|
label: 'SLA 达成率',
|
||||||
unit: '%',
|
unit: '%',
|
||||||
accent: '#10b981',
|
accent: 'var(--success)',
|
||||||
icon: 'mdi mdi-check-circle',
|
icon: 'mdi mdi-check-circle',
|
||||||
trend: 'up',
|
trend: 'up',
|
||||||
change: '3.1%',
|
change: '3.1%',
|
||||||
@@ -84,17 +84,17 @@ export const trendSeries = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const spendByCategory = [
|
export const spendByCategory = [
|
||||||
{ name: '机票', value: 182000, color: '#16a34a' },
|
{ name: '机票', value: 182000, color: 'var(--theme-primary)' },
|
||||||
{ name: '酒店', value: 146000, color: '#3b82f6' },
|
{ name: '酒店', value: 146000, color: 'var(--chart-blue)' },
|
||||||
{ name: '火车/用车', value: 78600, color: '#f59e0b' },
|
{ name: '火车/用车', value: 78600, color: 'var(--chart-amber)' },
|
||||||
{ name: '餐补及杂费', value: 55000, color: '#8b5cf6' }
|
{ name: '餐补及杂费', value: 55000, color: 'var(--chart-purple)' }
|
||||||
]
|
]
|
||||||
|
|
||||||
export const exceptionMix = [
|
export const exceptionMix = [
|
||||||
{ name: '住宿超标', value: 5, color: '#ef4444' },
|
{ name: '住宿超标', value: 5, color: 'var(--danger)' },
|
||||||
{ name: '重复报销', value: 3, color: '#f59e0b' },
|
{ name: '重复报销', value: 3, color: 'var(--warning)' },
|
||||||
{ name: '行程缺失', value: 3, color: '#8b5cf6' },
|
{ name: '行程缺失', value: 3, color: 'var(--chart-purple)' },
|
||||||
{ name: '发票异常', value: 3, color: '#3b82f6' }
|
{ name: '发票异常', value: 3, color: 'var(--chart-blue)' }
|
||||||
]
|
]
|
||||||
|
|
||||||
export const departmentRangeOptions = ['本周', '本月', '本季度']
|
export const departmentRangeOptions = ['本周', '本月', '本季度']
|
||||||
|
|||||||
@@ -1,26 +1,22 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { MotionPlugin } from '@vueuse/motion'
|
import { MotionPlugin } from '@vueuse/motion'
|
||||||
import PrimeVue from 'primevue/config'
|
import ElementPlus from 'element-plus'
|
||||||
import Aura from '@primevue/themes/aura'
|
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||||
|
import 'element-plus/dist/index.css'
|
||||||
import 'primeicons/primeicons.css'
|
import 'primeicons/primeicons.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router/index.js'
|
import router from './router/index.js'
|
||||||
|
import { installThemeSkin } from './composables/useThemeSkin.js'
|
||||||
import { installSessionNavigation } from './composables/useSystemState.js'
|
import { installSessionNavigation } from './composables/useSystemState.js'
|
||||||
|
import './assets/styles/element-plus-theme.css'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
installThemeSkin()
|
||||||
installSessionNavigation(router)
|
installSessionNavigation(router)
|
||||||
|
|
||||||
app.use(MotionPlugin)
|
app.use(MotionPlugin)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.use(PrimeVue, {
|
app.use(ElementPlus, { locale: zhCn })
|
||||||
theme: {
|
|
||||||
preset: Aura,
|
|
||||||
options: {
|
|
||||||
darkModeSelector: '.dark',
|
|
||||||
cssLayer: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
@@ -19,6 +19,14 @@ export const SECTION_DEFINITIONS = [
|
|||||||
longDesc: '统一维护企业名称、系统显示名称和版权信息,保存后会同步更新当前系统品牌展示。',
|
longDesc: '统一维护企业名称、系统显示名称和版权信息,保存后会同步更新当前系统品牌展示。',
|
||||||
actionLabel: '保存企业信息'
|
actionLabel: '保存企业信息'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'appearance',
|
||||||
|
label: '界面皮肤',
|
||||||
|
title: '界面皮肤与主色',
|
||||||
|
desc: '整体主色与控件观感',
|
||||||
|
longDesc: '设置当前浏览器的界面主色。默认使用浅蓝企业主题,后续可扩展为企业级统一下发。',
|
||||||
|
actionLabel: '保存皮肤设置'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'admin',
|
id: 'admin',
|
||||||
label: '管理员安全',
|
label: '管理员安全',
|
||||||
@@ -417,6 +425,7 @@ export function computeSectionStatus(state) {
|
|||||||
normalizeValue(state.companyForm.displayName) &&
|
normalizeValue(state.companyForm.displayName) &&
|
||||||
normalizeValue(state.companyForm.copyright)
|
normalizeValue(state.companyForm.copyright)
|
||||||
),
|
),
|
||||||
|
appearance: true,
|
||||||
admin: Boolean(
|
admin: Boolean(
|
||||||
normalizeValue(state.adminForm.adminAccount) &&
|
normalizeValue(state.adminForm.adminAccount) &&
|
||||||
normalizeValue(state.adminForm.adminEmail) &&
|
normalizeValue(state.adminForm.adminEmail) &&
|
||||||
|
|||||||
@@ -29,35 +29,35 @@
|
|||||||
<input v-model="listKeyword" type="search" placeholder="搜索单号、申请人、部门、归档类型..." />
|
<input v-model="listKeyword" type="search" placeholder="搜索单号、申请人、部门、归档类型..." />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<el-dropdown
|
||||||
v-for="dropdown in filterDropdowns"
|
v-for="menu in filterMenus"
|
||||||
:key="dropdown.key"
|
:key="menu.key"
|
||||||
class="archive-dropdown-filter"
|
class="archive-filter-control"
|
||||||
:class="{ open: openFilterKey === dropdown.key }"
|
trigger="click"
|
||||||
|
placement="bottom-start"
|
||||||
|
popper-class="archive-filter-menu"
|
||||||
|
@command="selectFilterValue(menu.key, $event)"
|
||||||
>
|
>
|
||||||
<button class="filter-btn" type="button" @click="toggleFilterDropdown(dropdown.key)">
|
<button class="filter-btn archive-filter-trigger" type="button">
|
||||||
<span>{{ dropdown.label }}</span>
|
<span>{{ menu.label }}</span>
|
||||||
<i class="mdi mdi-chevron-down"></i>
|
<i class="mdi mdi-chevron-down"></i>
|
||||||
</button>
|
</button>
|
||||||
<div
|
<template #dropdown>
|
||||||
v-if="openFilterKey === dropdown.key"
|
<el-dropdown-menu>
|
||||||
class="archive-dropdown-menu"
|
<el-dropdown-item
|
||||||
role="menu"
|
v-for="option in menu.options"
|
||||||
:aria-label="`${dropdown.label}筛选`"
|
:key="`${menu.key}-${option.value}`"
|
||||||
>
|
:command="option.value"
|
||||||
<button
|
:class="{ 'is-active': menu.activeValue === option.value }"
|
||||||
v-for="option in dropdown.options"
|
class="archive-filter-option"
|
||||||
:key="`${dropdown.key}-${option.value}`"
|
:aria-current="menu.activeValue === option.value ? 'true' : undefined"
|
||||||
type="button"
|
>
|
||||||
class="archive-dropdown-option"
|
<i v-if="menu.activeValue === option.value" class="mdi mdi-check"></i>
|
||||||
:class="{ active: dropdown.activeValue === option.value }"
|
<span>{{ option.label }}</span>
|
||||||
role="menuitem"
|
</el-dropdown-item>
|
||||||
@click="selectFilterValue(dropdown.key, option.value)"
|
</el-dropdown-menu>
|
||||||
>
|
</template>
|
||||||
{{ option.label }}
|
</el-dropdown>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -35,27 +35,19 @@
|
|||||||
<div class="budget-filter-set">
|
<div class="budget-filter-set">
|
||||||
<label>
|
<label>
|
||||||
<span>预算年度</span>
|
<span>预算年度</span>
|
||||||
<select v-model="filters.year">
|
<EnterpriseSelect v-model="filters.year" :options="yearOptions" />
|
||||||
<option v-for="year in years" :key="year" :value="year">{{ year }}年度</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span>预算季度</span>
|
<span>预算季度</span>
|
||||||
<select v-model="filters.quarter">
|
<EnterpriseSelect v-model="filters.quarter" :options="quarters" />
|
||||||
<option v-for="quarter in quarters" :key="quarter" :value="quarter">{{ quarter }}</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span>费用类型</span>
|
<span>费用类型</span>
|
||||||
<select v-model="filters.expenseType">
|
<EnterpriseSelect v-model="filters.expenseType" :options="expenseTypes" />
|
||||||
<option v-for="type in expenseTypes" :key="type">{{ type }}</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span>状态</span>
|
<span>状态</span>
|
||||||
<select v-model="filters.status">
|
<EnterpriseSelect v-model="filters.status" :options="statuses" />
|
||||||
<option v-for="status in statuses" :key="status">{{ status }}</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="budget-action-set">
|
<div class="budget-action-set">
|
||||||
@@ -158,14 +150,13 @@
|
|||||||
<i class="mdi mdi-chevron-right"></i>
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<label class="budget-page-size">
|
<EnterpriseSelect
|
||||||
<select v-model.number="budgetPageSize" aria-label="每页条数">
|
v-model="budgetPageSize"
|
||||||
<option v-for="size in budgetPageSizeOptions" :key="size" :value="size">
|
class="budget-page-size-select"
|
||||||
{{ size }} 条/页
|
:options="budgetPageSizeOptions"
|
||||||
</option>
|
aria-label="每页条数"
|
||||||
</select>
|
size="small"
|
||||||
<i class="mdi mdi-chevron-down"></i>
|
/>
|
||||||
</label>
|
|
||||||
<span class="budget-page-summary">
|
<span class="budget-page-summary">
|
||||||
共 {{ totalBudgetRows }} 条,当前第 {{ budgetPage }} / {{ totalBudgetPages }} 页
|
共 {{ totalBudgetRows }} 条,当前第 {{ budgetPage }} / {{ totalBudgetPages }} 页
|
||||||
</span>
|
</span>
|
||||||
@@ -232,23 +223,15 @@
|
|||||||
<div class="budget-edit-form-grid">
|
<div class="budget-edit-form-grid">
|
||||||
<label class="required">
|
<label class="required">
|
||||||
<span>预算年度</span>
|
<span>预算年度</span>
|
||||||
<select v-model="budgetEditForm.budgetYear">
|
<EnterpriseSelect v-model="budgetEditForm.budgetYear" :options="yearOptions" />
|
||||||
<option v-for="year in years" :key="year" :value="year">{{ year }}年度</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
<label class="required">
|
<label class="required">
|
||||||
<span>预算季度</span>
|
<span>预算季度</span>
|
||||||
<select v-model="budgetEditForm.budgetQuarter">
|
<EnterpriseSelect v-model="budgetEditForm.budgetQuarter" :options="quarters" />
|
||||||
<option v-for="quarter in quarters" :key="quarter" :value="quarter">{{ quarter }}</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
<label v-if="canSwitchDepartments" class="required">
|
<label v-if="canSwitchDepartments" class="required">
|
||||||
<span>所属部门</span>
|
<span>所属部门</span>
|
||||||
<select v-model="budgetEditForm.departmentCode">
|
<EnterpriseSelect v-model="budgetEditForm.departmentCode" :options="departmentOptions" />
|
||||||
<option v-for="department in departments" :key="department.code" :value="department.code">
|
|
||||||
{{ department.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
<label v-else class="required">
|
<label v-else class="required">
|
||||||
<span>所属部门</span>
|
<span>所属部门</span>
|
||||||
@@ -279,26 +262,19 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="row in budgetEditRows" :key="row.id">
|
<tr v-for="row in budgetEditRows" :key="row.id">
|
||||||
<td>
|
<td>
|
||||||
<select v-model="row.budgetSubjectCode" @change="syncBudgetRowSubject(row)">
|
<EnterpriseSelect
|
||||||
<option
|
v-model="row.budgetSubjectCode"
|
||||||
v-for="option in expenseTypeOptions"
|
:options="expenseTypeOptions"
|
||||||
:key="option.value"
|
size="small"
|
||||||
:value="option.value"
|
@change="syncBudgetRowSubject(row)"
|
||||||
>
|
/>
|
||||||
{{ option.label }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td><input v-model="row.budgetAmount" type="text" inputmode="decimal" /></td>
|
<td><input v-model="row.budgetAmount" type="text" inputmode="decimal" /></td>
|
||||||
<td>
|
<td>
|
||||||
<select v-model="row.warningThreshold">
|
<EnterpriseSelect v-model="row.warningThreshold" :options="warningOptions" size="small" />
|
||||||
<option v-for="warning in warningOptions" :key="warning">{{ warning }}</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select v-model="row.controlAction">
|
<EnterpriseSelect v-model="row.controlAction" :options="controlActionOptions" size="small" />
|
||||||
<option v-for="action in controlActionOptions" :key="action">{{ action }}</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td><input v-model="row.budgetRemark" type="text" /></td>
|
<td><input v-model="row.budgetRemark" type="text" /></td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -232,24 +232,7 @@
|
|||||||
<i class="mdi mdi-chevron-right"></i>
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-size-wrap">
|
<EnterpriseSelect v-model="pageSize" class="page-size-select" :options="pageSizeOptions" size="small" @change="changePageSize" />
|
||||||
<button class="page-size" type="button" @click="pageSizeOpen = !pageSizeOpen">
|
|
||||||
{{ pageSize }} 条/页 <i class="mdi mdi-chevron-down"></i>
|
|
||||||
</button>
|
|
||||||
<div v-if="pageSizeOpen" class="page-size-dropdown" role="listbox">
|
|
||||||
<button
|
|
||||||
v-for="size in pageSizes"
|
|
||||||
:key="size"
|
|
||||||
type="button"
|
|
||||||
role="option"
|
|
||||||
:aria-selected="pageSize === size"
|
|
||||||
:class="{ active: pageSize === size }"
|
|
||||||
@click="changePageSize(size)"
|
|
||||||
>
|
|
||||||
{{ size }} 条/页
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
</footer>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
@@ -258,6 +241,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, ref, watch } from 'vue'
|
import { computed, onMounted, ref, watch } from 'vue'
|
||||||
|
|
||||||
|
import EnterpriseSelect from '../components/shared/EnterpriseSelect.vue'
|
||||||
import TableEmptyState from '../components/shared/TableEmptyState.vue'
|
import TableEmptyState from '../components/shared/TableEmptyState.vue'
|
||||||
import TableLoadingState from '../components/shared/TableLoadingState.vue'
|
import TableLoadingState from '../components/shared/TableLoadingState.vue'
|
||||||
import { mapExpenseClaimToRequest } from '../composables/useRequests.js'
|
import { mapExpenseClaimToRequest } from '../composables/useRequests.js'
|
||||||
@@ -321,7 +305,7 @@ const FILTER_CONFIG_BY_SCOPE = {
|
|||||||
showDocumentType: false
|
showDocumentType: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const pageSizes = [10, 20, 50]
|
const pageSizeOptions = [10, 20, 50].map((size) => ({ label: `${size} 条/页`, value: size }))
|
||||||
const documentTypeOptions = [
|
const documentTypeOptions = [
|
||||||
{ value: DOCUMENT_TYPE_ALL, label: '单据类型' },
|
{ value: DOCUMENT_TYPE_ALL, label: '单据类型' },
|
||||||
{ value: DOCUMENT_TYPE_APPLICATION, label: '申请单' },
|
{ value: DOCUMENT_TYPE_APPLICATION, label: '申请单' },
|
||||||
@@ -356,7 +340,6 @@ const appliedStart = ref('')
|
|||||||
const appliedEnd = ref('')
|
const appliedEnd = ref('')
|
||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const pageSize = ref(20)
|
const pageSize = ref(20)
|
||||||
const pageSizeOpen = ref(false)
|
|
||||||
const archiveRows = ref([])
|
const archiveRows = ref([])
|
||||||
const approvalRows = ref([])
|
const approvalRows = ref([])
|
||||||
const supportingLoading = ref(false)
|
const supportingLoading = ref(false)
|
||||||
@@ -519,7 +502,7 @@ const emptyState = computed(() => {
|
|||||||
icon: 'mdi mdi-file-sign-outline',
|
icon: 'mdi mdi-file-sign-outline',
|
||||||
actionLabel: '',
|
actionLabel: '',
|
||||||
actionIcon: '',
|
actionIcon: '',
|
||||||
tone: 'emerald',
|
tone: 'theme',
|
||||||
artLabel: 'APPLY',
|
artLabel: 'APPLY',
|
||||||
tips: ['申请、报销、审批与归档统一在此查看', '申请批准后可继续发起报销']
|
tips: ['申请、报销、审批与归档统一在此查看', '申请批准后可继续发起报销']
|
||||||
}
|
}
|
||||||
@@ -534,7 +517,7 @@ const emptyState = computed(() => {
|
|||||||
icon: filtered ? 'mdi mdi-magnify-scan' : 'mdi mdi-file-document-multiple-outline',
|
icon: filtered ? 'mdi mdi-magnify-scan' : 'mdi mdi-file-document-multiple-outline',
|
||||||
actionLabel: '',
|
actionLabel: '',
|
||||||
actionIcon: '',
|
actionIcon: '',
|
||||||
tone: 'emerald',
|
tone: 'theme',
|
||||||
artLabel: filtered ? 'FILTER' : 'DOCS',
|
artLabel: filtered ? 'FILTER' : 'DOCS',
|
||||||
tips: ['单据中心已接入当前报销单据', '归档视角会同步已归档数据']
|
tips: ['单据中心已接入当前报销单据', '归档视角会同步已归档数据']
|
||||||
}
|
}
|
||||||
@@ -724,7 +707,6 @@ function handleEmptyAction() {
|
|||||||
|
|
||||||
function changePageSize(size) {
|
function changePageSize(size) {
|
||||||
pageSize.value = size
|
pageSize.value = size
|
||||||
pageSizeOpen.value = false
|
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -782,14 +764,12 @@ watch(
|
|||||||
[activeScopeTab, activeStatusTab, activeDocumentType, activeScene, listKeyword, appliedStart, appliedEnd],
|
[activeScopeTab, activeStatusTab, activeDocumentType, activeScene, listKeyword, appliedStart, appliedEnd],
|
||||||
() => {
|
() => {
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
pageSizeOpen.value = false
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
watch(activeFilterConfig, () => {
|
watch(activeFilterConfig, () => {
|
||||||
openFilterKey.value = ''
|
openFilterKey.value = ''
|
||||||
datePopover.value = false
|
datePopover.value = false
|
||||||
pageSizeOpen.value = false
|
|
||||||
|
|
||||||
if (!showDocumentTypeFilter.value) {
|
if (!showDocumentTypeFilter.value) {
|
||||||
activeDocumentType.value = DOCUMENT_TYPE_ALL
|
activeDocumentType.value = DOCUMENT_TYPE_ALL
|
||||||
|
|||||||
@@ -665,24 +665,13 @@
|
|||||||
<i class="mdi mdi-chevron-right"></i>
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-size-wrap">
|
<EnterpriseSelect
|
||||||
<button class="page-size" type="button" @click="togglePageSizeOpen">
|
v-model="pageSize"
|
||||||
{{ pageSize }} 条/页 <i class="mdi mdi-chevron-down"></i>
|
class="page-size-select"
|
||||||
</button>
|
:options="pageSizeOptions"
|
||||||
<div v-if="pageSizeOpen" class="page-size-dropdown" role="listbox">
|
size="small"
|
||||||
<button
|
@change="changePageSize"
|
||||||
v-for="size in pageSizes"
|
/>
|
||||||
:key="size"
|
|
||||||
type="button"
|
|
||||||
role="option"
|
|
||||||
:aria-selected="pageSize === size"
|
|
||||||
:class="{ active: pageSize === size }"
|
|
||||||
@click="changePageSize(size)"
|
|
||||||
>
|
|
||||||
{{ size }} 条/页
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
</footer>
|
||||||
</article>
|
</article>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|||||||
@@ -28,9 +28,12 @@
|
|||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span><em>*</em> 供应商</span>
|
<span><em>*</em> 供应商</span>
|
||||||
<select v-model="llmForm.mainProvider" @change="applyProviderPreset('main')">
|
<EnterpriseSelect
|
||||||
<option v-for="option in providerOptions" :key="option" :value="option">{{ option }}</option>
|
v-model="llmForm.mainProvider"
|
||||||
</select>
|
:options="providerOptions"
|
||||||
|
placeholder="选择供应商"
|
||||||
|
@change="applyProviderPreset('main')"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="field">
|
<label class="field">
|
||||||
@@ -101,9 +104,12 @@
|
|||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span><em>*</em> 供应商</span>
|
<span><em>*</em> 供应商</span>
|
||||||
<select v-model="llmForm.backupProvider" @change="applyProviderPreset('backup')">
|
<EnterpriseSelect
|
||||||
<option v-for="option in providerOptions" :key="option" :value="option">{{ option }}</option>
|
v-model="llmForm.backupProvider"
|
||||||
</select>
|
:options="providerOptions"
|
||||||
|
placeholder="选择供应商"
|
||||||
|
@change="applyProviderPreset('backup')"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="field">
|
<label class="field">
|
||||||
@@ -174,9 +180,12 @@
|
|||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span><em>*</em> 供应商</span>
|
<span><em>*</em> 供应商</span>
|
||||||
<select v-model="llmForm.embeddingProvider" @change="applyProviderPreset('embedding')">
|
<EnterpriseSelect
|
||||||
<option v-for="option in providerOptions" :key="option" :value="option">{{ option }}</option>
|
v-model="llmForm.embeddingProvider"
|
||||||
</select>
|
:options="providerOptions"
|
||||||
|
placeholder="选择供应商"
|
||||||
|
@change="applyProviderPreset('embedding')"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="field">
|
<label class="field">
|
||||||
@@ -251,9 +260,12 @@
|
|||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span><em>*</em> 供应商</span>
|
<span><em>*</em> 供应商</span>
|
||||||
<select v-model="llmForm.rerankerProvider" @change="applyProviderPreset('reranker')">
|
<EnterpriseSelect
|
||||||
<option v-for="option in providerOptions" :key="option" :value="option">{{ option }}</option>
|
v-model="llmForm.rerankerProvider"
|
||||||
</select>
|
:options="providerOptions"
|
||||||
|
placeholder="选择供应商"
|
||||||
|
@change="applyProviderPreset('reranker')"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="field">
|
<label class="field">
|
||||||
@@ -306,4 +318,3 @@
|
|||||||
|
|
||||||
<style scoped src="../assets/styles/views/settings-view-form.css"></style>
|
<style scoped src="../assets/styles/views/settings-view-form.css"></style>
|
||||||
<style scoped src="../assets/styles/views/settings-view.css"></style>
|
<style scoped src="../assets/styles/views/settings-view.css"></style>
|
||||||
|
|
||||||
|
|||||||
@@ -27,22 +27,22 @@
|
|||||||
|
|
||||||
<label class="filter-field">
|
<label class="filter-field">
|
||||||
<span>日志级别</span>
|
<span>日志级别</span>
|
||||||
<select v-model="systemLevelFilter">
|
<EnterpriseSelect
|
||||||
<option value="">全部</option>
|
v-model="systemLevelFilter"
|
||||||
<option v-for="level in systemLevelOptions" :key="level" :value="level">
|
:options="systemLevelFilterOptions"
|
||||||
{{ level }}
|
placeholder="全部"
|
||||||
</option>
|
size="small"
|
||||||
</select>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="filter-field">
|
<label class="filter-field">
|
||||||
<span>事件类型</span>
|
<span>事件类型</span>
|
||||||
<select v-model="systemEventTypeFilter">
|
<EnterpriseSelect
|
||||||
<option value="">全部</option>
|
v-model="systemEventTypeFilter"
|
||||||
<option v-for="eventType in systemEventTypeOptions" :key="eventType" :value="eventType">
|
:options="systemEventTypeFilterOptions"
|
||||||
{{ eventType }}
|
placeholder="全部"
|
||||||
</option>
|
size="small"
|
||||||
</select>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@@ -221,24 +221,13 @@
|
|||||||
<i class="mdi mdi-chevron-right"></i>
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-size-wrap">
|
<EnterpriseSelect
|
||||||
<button class="page-size" type="button" @click="pageSizeOpen = !pageSizeOpen">
|
v-model="pageSize"
|
||||||
{{ pageSize }} 条/页 <i class="mdi mdi-chevron-down"></i>
|
class="page-size-select"
|
||||||
</button>
|
:options="pageSizeOptions"
|
||||||
<div v-if="pageSizeOpen" class="page-size-dropdown" role="listbox">
|
size="small"
|
||||||
<button
|
@change="changePageSize"
|
||||||
v-for="size in pageSizes"
|
/>
|
||||||
:key="size"
|
|
||||||
type="button"
|
|
||||||
role="option"
|
|
||||||
:aria-selected="pageSize === size"
|
|
||||||
:class="{ active: pageSize === size }"
|
|
||||||
@click="changePageSize(size)"
|
|
||||||
>
|
|
||||||
{{ size }} 条/页
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,11 @@
|
|||||||
|
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span>加密方式</span>
|
<span>加密方式</span>
|
||||||
<select v-model="mailForm.encryption">
|
<EnterpriseSelect
|
||||||
<option value="SSL/TLS">SSL/TLS</option>
|
v-model="mailForm.encryption"
|
||||||
<option value="STARTTLS">STARTTLS</option>
|
:options="encryptionOptions"
|
||||||
<option value="None">无</option>
|
placeholder="选择加密方式"
|
||||||
</select>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="field">
|
<label class="field">
|
||||||
|
|||||||
@@ -26,9 +26,13 @@
|
|||||||
<article class="panel dashboard-card trend-panel">
|
<article class="panel dashboard-card trend-panel">
|
||||||
<div class="card-head">
|
<div class="card-head">
|
||||||
<h3>报销申请与审批趋势 <i class="mdi mdi-information-outline"></i></h3>
|
<h3>报销申请与审批趋势 <i class="mdi mdi-information-outline"></i></h3>
|
||||||
<select v-model="activeTrendRange" class="card-select" aria-label="趋势时间范围">
|
<EnterpriseSelect
|
||||||
<option v-for="range in trendRanges" :key="range">{{ range }}</option>
|
v-model="activeTrendRange"
|
||||||
</select>
|
class="card-select"
|
||||||
|
:options="trendRanges"
|
||||||
|
aria-label="趋势时间范围"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TrendChart
|
<TrendChart
|
||||||
@@ -52,17 +56,21 @@
|
|||||||
<h3>风险异常分布 <i class="mdi mdi-information-outline"></i></h3>
|
<h3>风险异常分布 <i class="mdi mdi-information-outline"></i></h3>
|
||||||
</div>
|
</div>
|
||||||
<DonutChart :items="riskLegend" :center-value="`${riskTotal}`" center-label="异常预警单" />
|
<DonutChart :items="riskLegend" :center-value="`${riskTotal}`" center-label="异常预警单" />
|
||||||
<p class="panel-note">* 近30天数据</p>
|
<p class="panel-note">* 近 30 天数据</p>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content-grid bottom-grid">
|
<div class="content-grid bottom-grid">
|
||||||
<article class="panel dashboard-card rank-panel">
|
<article class="panel dashboard-card rank-panel">
|
||||||
<div class="card-head">
|
<div class="card-head">
|
||||||
<h3>部门报销排行(待处理金额) <i class="mdi mdi-information-outline"></i></h3>
|
<h3>部门报销排行(待处理金额)<i class="mdi mdi-information-outline"></i></h3>
|
||||||
<select v-model="activeDepartmentRange" class="card-select" aria-label="部门排行时间范围">
|
<EnterpriseSelect
|
||||||
<option v-for="range in departmentRangeOptions" :key="range">{{ range }}</option>
|
v-model="activeDepartmentRange"
|
||||||
</select>
|
class="card-select"
|
||||||
|
:options="departmentRangeOptions"
|
||||||
|
aria-label="部门排行时间范围"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BarChart :items="rankedDepartments" />
|
<BarChart :items="rankedDepartments" />
|
||||||
@@ -99,7 +107,7 @@
|
|||||||
|
|
||||||
<article class="panel dashboard-card budget-panel">
|
<article class="panel dashboard-card budget-panel">
|
||||||
<div class="card-head">
|
<div class="card-head">
|
||||||
<h3>预算执行率(本月) <i class="mdi mdi-information-outline"></i></h3>
|
<h3>预算执行率(本月)<i class="mdi mdi-information-outline"></i></h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<GaugeChart
|
<GaugeChart
|
||||||
@@ -112,7 +120,6 @@
|
|||||||
<button type="button" class="text-link">查看详情 <i class="mdi mdi-chevron-right"></i></button>
|
<button type="button" class="text-link">查看详情 <i class="mdi mdi-chevron-right"></i></button>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -121,6 +128,7 @@ import TrendChart from '../components/charts/TrendChart.vue'
|
|||||||
import DonutChart from '../components/charts/DonutChart.vue'
|
import DonutChart from '../components/charts/DonutChart.vue'
|
||||||
import BarChart from '../components/charts/BarChart.vue'
|
import BarChart from '../components/charts/BarChart.vue'
|
||||||
import GaugeChart from '../components/charts/GaugeChart.vue'
|
import GaugeChart from '../components/charts/GaugeChart.vue'
|
||||||
|
import EnterpriseSelect from '../components/shared/EnterpriseSelect.vue'
|
||||||
|
|
||||||
import { useOverviewView } from '../composables/useOverviewView.js'
|
import { useOverviewView } from '../composables/useOverviewView.js'
|
||||||
|
|
||||||
@@ -128,8 +136,6 @@ defineProps({
|
|||||||
filteredRequests: { type: Array, required: true }
|
filteredRequests: { type: Array, required: true }
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['ask'])
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
activeDepartmentRange,
|
activeDepartmentRange,
|
||||||
activeTrend,
|
activeTrend,
|
||||||
|
|||||||
@@ -168,24 +168,13 @@
|
|||||||
<i class="mdi mdi-chevron-right"></i>
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-size-wrap">
|
<EnterpriseSelect
|
||||||
<button class="page-size" type="button" @click="pageSizeOpen = !pageSizeOpen">
|
v-model="pageSize"
|
||||||
{{ pageSize }} 条/页<i class="mdi mdi-chevron-down"></i>
|
class="page-size-select"
|
||||||
</button>
|
:options="pageSizeOptions"
|
||||||
<div v-if="pageSizeOpen" class="page-size-dropdown" role="listbox">
|
size="small"
|
||||||
<button
|
@change="changePageSize"
|
||||||
v-for="size in pageSizes"
|
/>
|
||||||
:key="size"
|
|
||||||
type="button"
|
|
||||||
role="option"
|
|
||||||
:aria-selected="pageSize === size"
|
|
||||||
:class="{ active: pageSize === size }"
|
|
||||||
@click="changePageSize(size)"
|
|
||||||
>
|
|
||||||
{{ size }} 条/页
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
</footer>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -135,14 +135,13 @@
|
|||||||
<button v-for="p in totalPages" :key="p" class="page-number" :class="{ active: currentPage === p }" type="button" :aria-current="currentPage === p ? 'page' : undefined" @click="currentPage = p">{{ p }}</button>
|
<button v-for="p in totalPages" :key="p" class="page-number" :class="{ active: currentPage === p }" type="button" :aria-current="currentPage === p ? 'page' : undefined" @click="currentPage = p">{{ p }}</button>
|
||||||
<button class="page-nav" type="button" :disabled="currentPage === totalPages" aria-label="下一页" @click="currentPage++"><i class="mdi mdi-chevron-right"></i></button>
|
<button class="page-nav" type="button" :disabled="currentPage === totalPages" aria-label="下一页" @click="currentPage++"><i class="mdi mdi-chevron-right"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-size-wrap">
|
<EnterpriseSelect
|
||||||
<button class="page-size" type="button" @click="pageSizeOpen = !pageSizeOpen">
|
v-model="pageSize"
|
||||||
{{ pageSize }} 条/页 <i class="mdi mdi-chevron-down"></i>
|
class="page-size-select"
|
||||||
</button>
|
:options="pageSizeOptions"
|
||||||
<div v-if="pageSizeOpen" class="page-size-dropdown" role="listbox">
|
size="small"
|
||||||
<button v-for="size in pageSizes" :key="size" type="button" role="option" :aria-selected="pageSize === size" :class="{ active: pageSize === size }" @click="changePageSize(size)">{{ size }} 条/页</button>
|
@change="changePageSize"
|
||||||
</div>
|
/>
|
||||||
</div>
|
|
||||||
</footer>
|
</footer>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -101,6 +101,53 @@
|
|||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="activeSection === 'appearance'">
|
||||||
|
<section class="settings-card">
|
||||||
|
<div class="card-head">
|
||||||
|
<div class="card-title-with-icon">
|
||||||
|
<div class="model-icon-box slate">
|
||||||
|
<i class="mdi mdi-palette-outline"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4>界面皮肤与企业主色</h4>
|
||||||
|
<p>只调整整体主色、焦点态、按钮和 Element Plus 控件颜色,不改变业务布局。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skin-option-grid">
|
||||||
|
<button
|
||||||
|
v-for="skin in themeSkinOptions"
|
||||||
|
:key="skin.id"
|
||||||
|
class="skin-option"
|
||||||
|
:class="{ active: activeThemeSkinId === skin.id }"
|
||||||
|
type="button"
|
||||||
|
@click="selectThemeSkin(skin.id)"
|
||||||
|
>
|
||||||
|
<span class="skin-swatch" aria-hidden="true">
|
||||||
|
<i :style="{ background: skin.primary }"></i>
|
||||||
|
<i :style="{ background: skin.primarySoftStrong }"></i>
|
||||||
|
<i :style="{ background: skin.secondary }"></i>
|
||||||
|
<i :style="{ background: skin.chartAmber }"></i>
|
||||||
|
</span>
|
||||||
|
<span class="skin-copy">
|
||||||
|
<strong>{{ skin.label }}</strong>
|
||||||
|
<small>{{ skin.desc }}</small>
|
||||||
|
</span>
|
||||||
|
<span v-if="activeThemeSkinId === skin.id" class="skin-current">当前</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skin-preview-panel">
|
||||||
|
<div>
|
||||||
|
<strong>{{ activeThemeSkin.label }}</strong>
|
||||||
|
<span>当前主色会同步到全局按钮、焦点环、下拉浮层和表单控件。</span>
|
||||||
|
</div>
|
||||||
|
<button class="skin-preview-action" type="button">主按钮</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template v-else-if="activeSection === 'admin'">
|
<template v-else-if="activeSection === 'admin'">
|
||||||
<section class="settings-card">
|
<section class="settings-card">
|
||||||
<div class="card-head">
|
<div class="card-head">
|
||||||
@@ -367,11 +414,11 @@
|
|||||||
|
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span>归档周期</span>
|
<span>归档周期</span>
|
||||||
<select v-model="pageState.logForm.archiveCycle">
|
<EnterpriseSelect
|
||||||
<option value="daily">按天归档</option>
|
v-model="pageState.logForm.archiveCycle"
|
||||||
<option value="weekly">按周归档</option>
|
:options="archiveCycleOptions"
|
||||||
<option value="monthly">按月归档</option>
|
placeholder="选择归档周期"
|
||||||
</select>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="field field-full">
|
<label class="field field-full">
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -241,11 +241,7 @@
|
|||||||
<td class="expense-type col-type">
|
<td class="expense-type col-type">
|
||||||
<template v-if="editingExpenseId === item.id">
|
<template v-if="editingExpenseId === item.id">
|
||||||
<div class="cell-editor">
|
<div class="cell-editor">
|
||||||
<select v-model="expenseEditor.itemType" class="editor-select">
|
<EnterpriseSelect v-model="expenseEditor.itemType" class="editor-select" :options="expenseTypeOptions" size="small" />
|
||||||
<option v-for="option in expenseTypeOptions" :key="option.value" :value="option.value">
|
|
||||||
{{ option.label }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<span>编辑费用项目</span>
|
<span>编辑费用项目</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -763,58 +759,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
<ConfirmDialog
|
<TravelRequestDeleteDialog :open="deleteDialogOpen" :badge="deleteActionLabel" :title="deleteDialogTitle" :description="deleteDialogDescription" :busy="deleteBusy" @close="closeDeleteDialog" @confirm="confirmDeleteRequest" />
|
||||||
:open="deleteDialogOpen"
|
|
||||||
:badge="deleteActionLabel"
|
|
||||||
badge-tone="danger"
|
|
||||||
:title="deleteDialogTitle"
|
|
||||||
:description="deleteDialogDescription"
|
|
||||||
cancel-text="取消"
|
|
||||||
confirm-text="确认删除"
|
|
||||||
busy-text="删除中..."
|
|
||||||
confirm-tone="danger"
|
|
||||||
confirm-icon="mdi mdi-trash-can-outline"
|
|
||||||
:busy="deleteBusy"
|
|
||||||
@close="closeDeleteDialog"
|
|
||||||
@confirm="confirmDeleteRequest"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ConfirmDialog
|
<TravelRequestApprovalDialog
|
||||||
:open="approveConfirmDialogOpen"
|
:open="approveConfirmDialogOpen"
|
||||||
:badge="approvalConfirmBadge"
|
:badge="approvalConfirmBadge"
|
||||||
badge-tone="info"
|
|
||||||
:title="approveConfirmTitle"
|
:title="approveConfirmTitle"
|
||||||
:description="approvalConfirmDescription"
|
:description="approvalConfirmDescription"
|
||||||
cancel-text="返回核对"
|
|
||||||
:confirm-text="approveConfirmText"
|
:confirm-text="approveConfirmText"
|
||||||
:busy-text="approveBusyText"
|
:busy-text="approveBusyText"
|
||||||
confirm-tone="primary"
|
|
||||||
confirm-icon="mdi mdi-check-circle-outline"
|
|
||||||
:busy="approveBusy"
|
:busy="approveBusy"
|
||||||
|
:document-no="request.documentNo || request.id"
|
||||||
|
:node="request.node"
|
||||||
|
:summary-label="approvalConfirmSummaryLabel"
|
||||||
|
:next-stage="approvalNextStage"
|
||||||
|
:opinion-title="approvalOpinionTitle"
|
||||||
|
:opinion="leaderOpinion"
|
||||||
@close="closeApproveConfirmDialog"
|
@close="closeApproveConfirmDialog"
|
||||||
@confirm="confirmApproveRequest"
|
@confirm="confirmApproveRequest"
|
||||||
>
|
/>
|
||||||
<div class="submit-confirm-summary" aria-label="领导审批通过摘要">
|
|
||||||
<div class="submit-confirm-row">
|
|
||||||
<span>单据编号</span>
|
|
||||||
<strong>{{ request.documentNo || request.id }}</strong>
|
|
||||||
</div>
|
|
||||||
<div class="submit-confirm-row">
|
|
||||||
<span>当前节点</span>
|
|
||||||
<strong>{{ request.node }}</strong>
|
|
||||||
</div>
|
|
||||||
<div class="submit-confirm-row">
|
|
||||||
<span>{{ approvalConfirmSummaryLabel }}</span>
|
|
||||||
<strong>{{ approvalNextStage }}</strong>
|
|
||||||
</div>
|
|
||||||
<div class="submit-confirm-row">
|
|
||||||
<span>{{ approvalOpinionTitle }}</span>
|
|
||||||
<strong>{{ leaderOpinion.trim() || '未填写' }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ConfirmDialog>
|
|
||||||
|
|
||||||
<ReturnReasonDialog
|
<TravelRequestReturnDialog
|
||||||
:open="returnDialogOpen"
|
:open="returnDialogOpen"
|
||||||
:title="`确认退回 ${request.id} 吗?`"
|
:title="`确认退回 ${request.id} 吗?`"
|
||||||
:description="returnDialogDescription"
|
:description="returnDialogDescription"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
|
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
|
||||||
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
|
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
|
||||||
@@ -102,7 +102,6 @@ export default {
|
|||||||
const activeTypeFilter = ref(ARCHIVE_FILTER_ALL)
|
const activeTypeFilter = ref(ARCHIVE_FILTER_ALL)
|
||||||
const activeDepartmentFilter = ref(ARCHIVE_FILTER_ALL)
|
const activeDepartmentFilter = ref(ARCHIVE_FILTER_ALL)
|
||||||
const activeArchiveMonthFilter = ref(ARCHIVE_FILTER_ALL)
|
const activeArchiveMonthFilter = ref(ARCHIVE_FILTER_ALL)
|
||||||
const openFilterKey = ref('')
|
|
||||||
const selectedClaimId = ref('')
|
const selectedClaimId = ref('')
|
||||||
const listKeyword = ref('')
|
const listKeyword = ref('')
|
||||||
const rows = ref([])
|
const rows = ref([])
|
||||||
@@ -118,7 +117,7 @@ export default {
|
|||||||
const departmentFilterLabel = computed(() => resolveFilterLabel(departmentFilterOptions.value, activeDepartmentFilter.value, '所属部门'))
|
const departmentFilterLabel = computed(() => resolveFilterLabel(departmentFilterOptions.value, activeDepartmentFilter.value, '所属部门'))
|
||||||
const archiveMonthFilterLabel = computed(() => resolveFilterLabel(archiveMonthFilterOptions.value, activeArchiveMonthFilter.value, '归档月份'))
|
const archiveMonthFilterLabel = computed(() => resolveFilterLabel(archiveMonthFilterOptions.value, activeArchiveMonthFilter.value, '归档月份'))
|
||||||
|
|
||||||
const filterDropdowns = computed(() => [
|
const filterMenus = computed(() => [
|
||||||
{
|
{
|
||||||
key: 'risk',
|
key: 'risk',
|
||||||
label: riskFilterLabel.value,
|
label: riskFilterLabel.value,
|
||||||
@@ -210,7 +209,6 @@ export default {
|
|||||||
activeDepartmentFilter.value = ARCHIVE_FILTER_ALL
|
activeDepartmentFilter.value = ARCHIVE_FILTER_ALL
|
||||||
activeArchiveMonthFilter.value = ARCHIVE_FILTER_ALL
|
activeArchiveMonthFilter.value = ARCHIVE_FILTER_ALL
|
||||||
listKeyword.value = ''
|
listKeyword.value = ''
|
||||||
openFilterKey.value = ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEmptyAction() {
|
function handleEmptyAction() {
|
||||||
@@ -222,10 +220,6 @@ export default {
|
|||||||
resetListFilters()
|
resetListFilters()
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleFilterDropdown(key) {
|
|
||||||
openFilterKey.value = openFilterKey.value === key ? '' : key
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectFilterValue(key, value) {
|
function selectFilterValue(key, value) {
|
||||||
if (key === 'risk') {
|
if (key === 'risk') {
|
||||||
activeRiskFilter.value = value
|
activeRiskFilter.value = value
|
||||||
@@ -237,18 +231,6 @@ export default {
|
|||||||
activeArchiveMonthFilter.value = value
|
activeArchiveMonthFilter.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
openFilterKey.value = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDocumentClick(event) {
|
|
||||||
const target = event.target
|
|
||||||
if (!(target instanceof Element)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target.closest('.archive-dropdown-filter')) {
|
|
||||||
openFilterKey.value = ''
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeSelectedDetail() {
|
function closeSelectedDetail() {
|
||||||
@@ -278,14 +260,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
document.addEventListener('click', handleDocumentClick)
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
document.removeEventListener('click', handleDocumentClick)
|
|
||||||
})
|
|
||||||
|
|
||||||
void reload()
|
void reload()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -293,11 +267,10 @@ export default {
|
|||||||
archiveEmptyState,
|
archiveEmptyState,
|
||||||
closeSelectedDetail,
|
closeSelectedDetail,
|
||||||
error,
|
error,
|
||||||
filterDropdowns,
|
filterMenus,
|
||||||
handleEmptyAction,
|
handleEmptyAction,
|
||||||
listKeyword,
|
listKeyword,
|
||||||
loading,
|
loading,
|
||||||
openFilterKey,
|
|
||||||
reload,
|
reload,
|
||||||
resetListFilters,
|
resetListFilters,
|
||||||
rows,
|
rows,
|
||||||
@@ -305,7 +278,6 @@ export default {
|
|||||||
selectedRow,
|
selectedRow,
|
||||||
showEmpty,
|
showEmpty,
|
||||||
tabs,
|
tabs,
|
||||||
toggleFilterDropdown,
|
|
||||||
visibleRows
|
visibleRows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||||
|
|
||||||
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
|
import AuditAssetList from '../../components/audit/AuditAssetList.vue'
|
||||||
|
import AuditJsonRiskRuleDetail from '../../components/audit/AuditJsonRiskRuleDetail.vue'
|
||||||
|
import AuditRuleDialogs from '../../components/audit/AuditRuleDialogs.vue'
|
||||||
|
import AuditSpreadsheetChangeDrawer from '../../components/audit/AuditSpreadsheetChangeDrawer.vue'
|
||||||
|
import AuditSpreadsheetRuleDetail from '../../components/audit/AuditSpreadsheetRuleDetail.vue'
|
||||||
|
import AuditVersionTimelineDrawer from '../../components/audit/AuditVersionTimelineDrawer.vue'
|
||||||
import { fetchEmployees } from '../../services/employees.js'
|
import { fetchEmployees } from '../../services/employees.js'
|
||||||
import RiskRuleFlowDiagram from '../../components/shared/RiskRuleFlowDiagram.vue'
|
|
||||||
import RiskRuleTestDialog from '../../components/shared/RiskRuleTestDialog.vue'
|
|
||||||
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
|
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
|
||||||
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
|
|
||||||
import { useSystemState } from '../../composables/useSystemState.js'
|
import { useSystemState } from '../../composables/useSystemState.js'
|
||||||
import { useToast } from '../../composables/useToast.js'
|
import { useToast } from '../../composables/useToast.js'
|
||||||
import {
|
import {
|
||||||
@@ -77,11 +79,13 @@ import {
|
|||||||
export default {
|
export default {
|
||||||
name: 'AuditView',
|
name: 'AuditView',
|
||||||
components: {
|
components: {
|
||||||
ConfirmDialog,
|
AuditAssetList,
|
||||||
RiskRuleFlowDiagram,
|
AuditJsonRiskRuleDetail,
|
||||||
RiskRuleTestDialog,
|
AuditRuleDialogs,
|
||||||
TableLoadingState,
|
AuditSpreadsheetChangeDrawer,
|
||||||
TableEmptyState
|
AuditSpreadsheetRuleDetail,
|
||||||
|
AuditVersionTimelineDrawer,
|
||||||
|
TableLoadingState
|
||||||
},
|
},
|
||||||
emits: ['detail-open-change'],
|
emits: ['detail-open-change'],
|
||||||
setup(_, { emit }) {
|
setup(_, { emit }) {
|
||||||
@@ -115,6 +119,10 @@ export default {
|
|||||||
const reviewSubmitReviewer = ref('')
|
const reviewSubmitReviewer = ref('')
|
||||||
const reviewSubmitReviewerLoading = ref(false)
|
const reviewSubmitReviewerLoading = ref(false)
|
||||||
const reviewSubmitReviewerOptions = ref([])
|
const reviewSubmitReviewerOptions = ref([])
|
||||||
|
const riskRuleAttachmentOptions = [
|
||||||
|
{ label: '是', value: true },
|
||||||
|
{ label: '否', value: false }
|
||||||
|
]
|
||||||
const riskRuleCreateOpen = ref(false)
|
const riskRuleCreateOpen = ref(false)
|
||||||
const riskRuleCreateForm = ref(createDefaultRiskRuleForm())
|
const riskRuleCreateForm = ref(createDefaultRiskRuleForm())
|
||||||
const riskRuleTestOpen = ref(false)
|
const riskRuleTestOpen = ref(false)
|
||||||
@@ -466,7 +474,7 @@ export default {
|
|||||||
icon: hasFilters ? 'mdi mdi-tune-variant' : 'mdi mdi-view-grid-outline',
|
icon: hasFilters ? 'mdi mdi-tune-variant' : 'mdi mdi-view-grid-outline',
|
||||||
actionLabel: hasFilters ? '清空筛选' : '',
|
actionLabel: hasFilters ? '清空筛选' : '',
|
||||||
actionIcon: hasFilters ? 'mdi mdi-filter-remove-outline' : '',
|
actionIcon: hasFilters ? 'mdi mdi-filter-remove-outline' : '',
|
||||||
tone: hasFilters ? 'emerald' : 'slate',
|
tone: hasFilters ? 'primary' : 'slate',
|
||||||
artLabel: hasFilters ? 'FILTER' : 'QUEUE',
|
artLabel: hasFilters ? 'FILTER' : 'QUEUE',
|
||||||
tips: hasFilters
|
tips: hasFilters
|
||||||
? [
|
? [
|
||||||
@@ -956,7 +964,7 @@ export default {
|
|||||||
if (!canUploadSpreadsheet.value) {
|
if (!canUploadSpreadsheet.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
spreadsheetUploadInput.value?.click()
|
spreadsheetUploadInput.value?.click?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadSpreadsheetFile() {
|
async function downloadSpreadsheetFile() {
|
||||||
@@ -1003,9 +1011,7 @@ export default {
|
|||||||
toast(error?.message || '规则表内容导入失败,请稍后重试。')
|
toast(error?.message || '规则表内容导入失败,请稍后重试。')
|
||||||
} finally {
|
} finally {
|
||||||
actionState.value = ''
|
actionState.value = ''
|
||||||
if (spreadsheetUploadInput.value) {
|
spreadsheetUploadInput.value?.reset?.()
|
||||||
spreadsheetUploadInput.value.value = ''
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1916,6 +1922,7 @@ export default {
|
|||||||
reviewSubmitReviewer,
|
reviewSubmitReviewer,
|
||||||
reviewSubmitReviewerLoading,
|
reviewSubmitReviewerLoading,
|
||||||
reviewSubmitReviewerOptions,
|
reviewSubmitReviewerOptions,
|
||||||
|
riskRuleAttachmentOptions,
|
||||||
riskRuleCreateOpen,
|
riskRuleCreateOpen,
|
||||||
riskRuleCreateForm,
|
riskRuleCreateForm,
|
||||||
riskRuleCreateBusy,
|
riskRuleCreateBusy,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { computed, onMounted, ref, watch } from 'vue'
|
|||||||
|
|
||||||
import BudgetTrendChart from '../../components/charts/BudgetTrendChart.vue'
|
import BudgetTrendChart from '../../components/charts/BudgetTrendChart.vue'
|
||||||
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
|
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
|
||||||
|
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
|
||||||
import { createBudgetAllocation, fetchBudgetSummary } from '../../services/budgets.js'
|
import { createBudgetAllocation, fetchBudgetSummary } from '../../services/budgets.js'
|
||||||
import { fetchEmployeeMeta } from '../../services/employees.js'
|
import { fetchEmployeeMeta } from '../../services/employees.js'
|
||||||
import {
|
import {
|
||||||
@@ -177,7 +178,8 @@ export default {
|
|||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
BudgetTrendChart,
|
BudgetTrendChart,
|
||||||
ConfirmDialog
|
ConfirmDialog,
|
||||||
|
EnterpriseSelect
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const departments = ref(FALLBACK_DEPARTMENTS)
|
const departments = ref(FALLBACK_DEPARTMENTS)
|
||||||
@@ -215,6 +217,14 @@ export default {
|
|||||||
const isDepartmentBudgetMonitor = computed(
|
const isDepartmentBudgetMonitor = computed(
|
||||||
() => isBudgetMonitorUser(props.currentUser) && !canSwitchDepartments.value && !isExecutiveUser(props.currentUser)
|
() => isBudgetMonitorUser(props.currentUser) && !canSwitchDepartments.value && !isExecutiveUser(props.currentUser)
|
||||||
)
|
)
|
||||||
|
const yearOptions = BUDGET_YEAR_OPTIONS.map((year) => ({ label: `${year}年度`, value: year }))
|
||||||
|
const budgetPageSizeOptions = BUDGET_PAGE_SIZE_OPTIONS.map((size) => ({ label: `${size} 条/页`, value: size }))
|
||||||
|
const departmentOptions = computed(() =>
|
||||||
|
departments.value.map((department) => ({
|
||||||
|
label: department.name,
|
||||||
|
value: department.code
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
const activeDepartment = computed(() =>
|
const activeDepartment = computed(() =>
|
||||||
departments.value.find((item) => item.code === activeDepartmentCode.value) || departments.value[0]
|
departments.value.find((item) => item.code === activeDepartmentCode.value) || departments.value[0]
|
||||||
@@ -273,7 +283,7 @@ export default {
|
|||||||
value: `¥${currency(totals.value.total)}`,
|
value: `¥${currency(totals.value.total)}`,
|
||||||
yoy: comparison('+8.42%', 'up'),
|
yoy: comparison('+8.42%', 'up'),
|
||||||
mom: comparison('+2.16%', 'up'),
|
mom: comparison('+2.16%', 'up'),
|
||||||
tone: 'green',
|
tone: 'primary',
|
||||||
icon: 'mdi mdi-wallet-outline'
|
icon: 'mdi mdi-wallet-outline'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -281,7 +291,7 @@ export default {
|
|||||||
value: `¥${currency(totals.value.used)}`,
|
value: `¥${currency(totals.value.used)}`,
|
||||||
yoy: comparison('+12.68%', 'up'),
|
yoy: comparison('+12.68%', 'up'),
|
||||||
mom: comparison('+4.35%', 'up'),
|
mom: comparison('+4.35%', 'up'),
|
||||||
tone: 'blue',
|
tone: 'info',
|
||||||
icon: 'mdi mdi-chart-line'
|
icon: 'mdi mdi-chart-line'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -289,7 +299,7 @@ export default {
|
|||||||
value: `¥${currency(totals.value.occupied)}`,
|
value: `¥${currency(totals.value.occupied)}`,
|
||||||
yoy: comparison('+6.37%', 'up'),
|
yoy: comparison('+6.37%', 'up'),
|
||||||
mom: comparison('-1.84%', 'down'),
|
mom: comparison('-1.84%', 'down'),
|
||||||
tone: 'orange',
|
tone: 'warning',
|
||||||
icon: 'mdi mdi-briefcase-check-outline'
|
icon: 'mdi mdi-briefcase-check-outline'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -297,7 +307,7 @@ export default {
|
|||||||
value: `¥${currency(totals.value.left)}`,
|
value: `¥${currency(totals.value.left)}`,
|
||||||
yoy: comparison('-3.26%', 'down'),
|
yoy: comparison('-3.26%', 'down'),
|
||||||
mom: comparison('-2.08%', 'down'),
|
mom: comparison('-2.08%', 'down'),
|
||||||
tone: 'green',
|
tone: 'primary',
|
||||||
icon: 'mdi mdi-cash'
|
icon: 'mdi mdi-cash'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@@ -612,7 +622,7 @@ export default {
|
|||||||
budgetPage: currentBudgetPage,
|
budgetPage: currentBudgetPage,
|
||||||
budgetPageNumbers,
|
budgetPageNumbers,
|
||||||
budgetPageSize,
|
budgetPageSize,
|
||||||
budgetPageSizeOptions: BUDGET_PAGE_SIZE_OPTIONS,
|
budgetPageSizeOptions,
|
||||||
canEditBudget,
|
canEditBudget,
|
||||||
canSwitchDepartments,
|
canSwitchDepartments,
|
||||||
closeBudgetEditDialog,
|
closeBudgetEditDialog,
|
||||||
@@ -633,6 +643,7 @@ export default {
|
|||||||
confirmDeleteRow,
|
confirmDeleteRow,
|
||||||
cancelDeleteRow,
|
cancelDeleteRow,
|
||||||
cancelSaveBudget,
|
cancelSaveBudget,
|
||||||
|
departmentOptions,
|
||||||
requestSaveBudget,
|
requestSaveBudget,
|
||||||
statusOptions: BUDGET_STATUS_OPTIONS,
|
statusOptions: BUDGET_STATUS_OPTIONS,
|
||||||
statuses: ['全部', '正常', '预警', '管控'],
|
statuses: ['全部', '正常', '预警', '管控'],
|
||||||
@@ -645,6 +656,7 @@ export default {
|
|||||||
visibleDepartments,
|
visibleDepartments,
|
||||||
warningOptions: BUDGET_WARNING_OPTIONS,
|
warningOptions: BUDGET_WARNING_OPTIONS,
|
||||||
warnings,
|
warnings,
|
||||||
|
yearOptions,
|
||||||
years: BUDGET_YEAR_OPTIONS
|
years: BUDGET_YEAR_OPTIONS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||||
|
|
||||||
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
|
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
|
||||||
|
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
|
||||||
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
|
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
|
||||||
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
|
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
|
||||||
import { useToast } from '../../composables/useToast.js'
|
import { useToast } from '../../composables/useToast.js'
|
||||||
@@ -438,6 +439,7 @@ export default {
|
|||||||
name: 'EmployeeManagementView',
|
name: 'EmployeeManagementView',
|
||||||
components: {
|
components: {
|
||||||
ConfirmDialog,
|
ConfirmDialog,
|
||||||
|
EnterpriseSelect,
|
||||||
TableLoadingState,
|
TableLoadingState,
|
||||||
TableEmptyState
|
TableEmptyState
|
||||||
},
|
},
|
||||||
@@ -457,7 +459,7 @@ export default {
|
|||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const pageSize = ref(10)
|
const pageSize = ref(10)
|
||||||
const pageSizes = [10, 20, 50]
|
const pageSizes = [10, 20, 50]
|
||||||
const pageSizeOpen = ref(false)
|
const pageSizeOptions = pageSizes.map((size) => ({ label: `${size} 条/页`, value: size }))
|
||||||
const actionState = ref('')
|
const actionState = ref('')
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const errorMessage = ref('')
|
const errorMessage = ref('')
|
||||||
@@ -713,7 +715,7 @@ export default {
|
|||||||
icon: hasEmployeeFilters.value ? 'mdi mdi-account-search-outline' : 'mdi mdi-badge-account-horizontal-outline',
|
icon: hasEmployeeFilters.value ? 'mdi mdi-account-search-outline' : 'mdi mdi-badge-account-horizontal-outline',
|
||||||
actionLabel: hasEmployeeFilters.value ? '清空筛选' : '查看全部员工',
|
actionLabel: hasEmployeeFilters.value ? '清空筛选' : '查看全部员工',
|
||||||
actionIcon: hasEmployeeFilters.value ? 'mdi mdi-filter-remove-outline' : 'mdi mdi-format-list-bulleted',
|
actionIcon: hasEmployeeFilters.value ? 'mdi mdi-filter-remove-outline' : 'mdi mdi-format-list-bulleted',
|
||||||
tone: hasEmployeeFilters.value ? 'emerald' : 'slate',
|
tone: hasEmployeeFilters.value ? 'primary' : 'slate',
|
||||||
artLabel: hasEmployeeFilters.value ? 'FILTER' : 'STATUS',
|
artLabel: hasEmployeeFilters.value ? 'FILTER' : 'STATUS',
|
||||||
tips: hasEmployeeFilters.value
|
tips: hasEmployeeFilters.value
|
||||||
? ['关键词、部门、职级和角色条件会叠加生效', '也可以直接搜索姓名、工号或岗位']
|
? ['关键词、部门、职级和角色条件会叠加生效', '也可以直接搜索姓名、工号或岗位']
|
||||||
@@ -791,7 +793,6 @@ export default {
|
|||||||
|
|
||||||
watch(filteredEmployees, () => {
|
watch(filteredEmployees, () => {
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
pageSizeOpen.value = false
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function resetFilters() {
|
function resetFilters() {
|
||||||
@@ -801,7 +802,6 @@ export default {
|
|||||||
selectedRole.value = ''
|
selectedRole.value = ''
|
||||||
activeTab.value = DEFAULT_STATUS_TABS[0]
|
activeTab.value = DEFAULT_STATUS_TABS[0]
|
||||||
activeFilterPopover.value = ''
|
activeFilterPopover.value = ''
|
||||||
pageSizeOpen.value = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEmployeeEmptyAction() {
|
function handleEmployeeEmptyAction() {
|
||||||
@@ -815,14 +815,9 @@ export default {
|
|||||||
|
|
||||||
function changePageSize(size) {
|
function changePageSize(size) {
|
||||||
pageSize.value = size
|
pageSize.value = size
|
||||||
pageSizeOpen.value = false
|
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function togglePageSizeOpen() {
|
|
||||||
pageSizeOpen.value = !pageSizeOpen.value
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleFilterPopover(name) {
|
function toggleFilterPopover(name) {
|
||||||
activeFilterPopover.value = activeFilterPopover.value === name ? '' : name
|
activeFilterPopover.value = activeFilterPopover.value === name ? '' : name
|
||||||
}
|
}
|
||||||
@@ -852,7 +847,6 @@ export default {
|
|||||||
|
|
||||||
if (!(target instanceof Element)) {
|
if (!(target instanceof Element)) {
|
||||||
closeFilterPopover()
|
closeFilterPopover()
|
||||||
pageSizeOpen.value = false
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,13 +862,8 @@ export default {
|
|||||||
closeDepartmentPicker()
|
closeDepartmentPicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target.closest('.page-size-wrap')) {
|
|
||||||
pageSizeOpen.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
target.closest('.picker-filter') ||
|
target.closest('.picker-filter') ||
|
||||||
target.closest('.page-size-wrap') ||
|
|
||||||
target.closest('.manager-picker') ||
|
target.closest('.manager-picker') ||
|
||||||
target.closest('.department-picker')
|
target.closest('.department-picker')
|
||||||
) {
|
) {
|
||||||
@@ -1437,7 +1426,7 @@ export default {
|
|||||||
currentPage,
|
currentPage,
|
||||||
pageSize,
|
pageSize,
|
||||||
pageSizes,
|
pageSizes,
|
||||||
pageSizeOpen,
|
pageSizeOptions,
|
||||||
departmentOptions,
|
departmentOptions,
|
||||||
gradeOptions,
|
gradeOptions,
|
||||||
roleFilterOptions,
|
roleFilterOptions,
|
||||||
@@ -1475,7 +1464,6 @@ export default {
|
|||||||
disableDialogOpen,
|
disableDialogOpen,
|
||||||
disableEmployeeAccount,
|
disableEmployeeAccount,
|
||||||
changePageSize,
|
changePageSize,
|
||||||
togglePageSizeOpen,
|
|
||||||
toggleFilterPopover,
|
toggleFilterPopover,
|
||||||
closeFilterPopover,
|
closeFilterPopover,
|
||||||
selectFilter,
|
selectFilter,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { testModelConnectivity } from '../../services/settings.js'
|
import { testModelConnectivity } from '../../services/settings.js'
|
||||||
import { useToast } from '../../composables/useToast.js'
|
import { useToast } from '../../composables/useToast.js'
|
||||||
|
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
|
||||||
|
|
||||||
const MODEL_SECRET_MASK = '********'
|
const MODEL_SECRET_MASK = '********'
|
||||||
|
|
||||||
@@ -101,6 +102,9 @@ function isModelSecretMask(value) {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'LlmSettingsPanel',
|
name: 'LlmSettingsPanel',
|
||||||
|
components: {
|
||||||
|
EnterpriseSelect
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
llmForm: {
|
llmForm: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user