Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
A
audit_project_manager
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
David Yang
audit_project_manager
Commits
190e6b24
Commit
190e6b24
authored
Aug 31, 2026
by
Andy-bubu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: refine dashboard chart palette and headings
parent
b9f397bf
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
165 additions
and
62 deletions
+165
-62
xinyuan-11-app-migration-prompt.md
docs/xinyuan-11-app-migration-prompt.md
+27
-22
xinyuan-design-system.md
docs/xinyuan-design-system.md
+12
-2
xinyuan-ui-audit.md
docs/xinyuan-ui-audit.md
+5
-2
XinyuanEChart.jsx
src/components/XinyuanEChart.jsx
+18
-0
chartPalette.js
src/design-system/chartPalette.js
+46
-10
shell.css
src/design-system/shell.css
+17
-0
theme.css
src/design-system/theme.css
+20
-16
tokens.css
src/design-system/tokens.css
+4
-4
AuditProjectDashboardPage.jsx
src/pages/project_manager_xy/AuditProjectDashboardPage.jsx
+16
-6
No files found.
docs/xinyuan-11-app-migration-prompt.md
View file @
190e6b24
...
...
@@ -8,10 +8,10 @@
## 0. 唯一视觉基准
以已完成并验收的“审计项目管理”应用
和“问题整改”应用的
真实代码为唯一实现基准:
以已完成并验收的“审计项目管理”应用真实代码为唯一实现基准:
-
基准目录固定为
`/Users/liuchenlong/Desktop/job/audit_project_manager`
;只读取该项目的真实实现和文档作为视觉、交互、组件结构与验收基准。
-
读取审计项目管理的 docs/xinyuan-design-system.md、docs/ui-architecture.md、docs/ui-migration-checklist.md、src/design-system/theme.css、src/design-system/tokens.css、src/design-system/shell.css,以及 AppShell、DashboardSidebar、DashboardNavbar、ApplicationSwitcherDialog、DataTable、XinyuanEChart 等真实实现。
-
问题整改基准目录为 /Users/liuchenlong/Desktop/job/problem_rectification。先读取最近提交记录和对应模块的真实实现,不得只按文字描述自行重写。
-
这不是重新设计。登录页、深色 Sidebar、Navbar、应用切换 Modal、页面边距、Surface 层级、Tabs、筛选、DataGrid、分页、弹窗、KPI、图表、空状态和交互必须与基准的结构、尺寸、间距、层级和行为一致;目标应用只替换自己的业务数据、应用标识、路由、Subject/View 和权限来源。
## 1. 开始前硬门槛
...
...
@@ -25,15 +25,22 @@ git status --short
git branch --show-current
~~~
当前项目已安装 HeroUI Pro:
-
不要执行 hpsetup。
-
不要询问、搜索、输出或保存 HeroUI Pro 授权值。
-
只读取当前项目自己的 package.json、锁文件和 node_modules。
HeroUI Pro 必须在当前目标项目中独立正式安装后才能开始 UI 修改。发现安装缺失、版本不一致、导出方式差异或校验命令不兼容时,优先在当前项目内修复并重新验证,不要因为可修复的环境问题停止整个迁移。
-
先只读取当前项目自己的 package.json、锁文件和 node_modules,检查是否缺失、版本是否一致。
-
如果缺失或 package.json 与 node_modules 实际版本不一致,先在当前项目根目录执行本次用户提供的正式安装命令:
`pnpm dlx hpsetup@latest <本次用户提供的授权值>`
。
-
`<本次用户提供的授权值>`
只能来自用户当前消息或当前任务上下文;禁止从其他项目、Shell 历史、文档、环境文件或 Git 中搜索。
-
不得把授权值写入源码、文档、环境文件、package.json、锁文件或 Git 提交;命令输出中也不要回显授权值。
-
如果 pnpm 不存在,先在当前环境解决 pnpm,再重新执行同一条正式安装命令;网络、缓存、锁文件或安装器提示可修复时,完成修复后继续重试。
-
安装命令执行后,若 package.json 与 node_modules 仍不一致,检查包管理器锁文件、重复安装位置和当前 Node 解析路径,在当前项目内统一到声明版本,再重新安装/验证。
-
CommonJS
`require.resolve('@heroui-pro/react')`
因 package exports 只提供 ESM 而失败时,不得判定安装失败;改用
`node --input-type=module`
的
`import.meta.resolve('@heroui-pro/react')`
验证。
-
`@heroui-pro/react/css`
被 Node 直接动态 import 而出现
`ERR_UNKNOWN_FILE_EXTENSION`
时,不得判定安装失败;用
`import.meta.resolve`
、package exports 和 CSS 文件存在性验证,然后通过项目构建验证 bundler 可加载。
-
已知的版本、解析器、锁文件、缓存、pnpm、CSS loader、ESM/CJS 兼容问题必须先修复并继续迁移。只有在当前项目内反复修复仍无法安装/解析,或发现包来源是跨项目依赖时,才暂停并报告具体阻塞。
-
禁止相邻项目 node_modules、跨项目 file: 依赖、绝对 /Users/... 依赖、软链接、本机 vendor 包。
-
不得
修改 HeroUI/HeroUI Pro 的版本或安装方式
。
-
不得
擅自修改 HeroUI/HeroUI Pro 版本或安装方式;版本变化只能由正式安装命令产生
。
在任何 UI 修改前验证并报告:
在任何 UI 修改前
,先完成安装(如需要),再
验证并报告:
~~~
node -p "require('./node_modules/@heroui-pro/react/package.json').version"
...
...
@@ -55,7 +62,11 @@ for (const spec of [
NODE
~~~
@heroui-pro/react/css 是 CSS style/default 导出,不是 Node 可执行 JS;不要把 Node 的 ERR_UNKNOWN_FILE_EXTENSION 误判成包缺失。必须同时确认 package exports 指向 dist/css/index.css,并以项目构建成功证明样式可被 bundler 加载。JS 子路径出现任何导入错误时停止 UI 改造,只报告错误。
@heroui-pro/react/css 是 CSS style/default 导出,不是 Node 可执行 JS;不要把 Node 的 ERR_UNKNOWN_FILE_EXTENSION 误判成包缺失。必须同时确认 package exports 指向 dist/css/index.css,并以项目构建成功证明样式可被 bundler 加载。JS 子路径若出现导入错误,先检查导出版本、解析器和依赖图并修复;修复后仍无法解析才暂停。
### 修复优先原则
后续审计、迁移和验收遇到版本、锁文件、包管理器、ESM/CJS、CSS loader、组件导出、旧组件引用、构建、路由 base、Portal 或浏览器控制台差异时,先判断是否属于当前项目内可修复的问题:读取真实配置和官方 API,按本规范修正,重新执行验证并继续迁移。不要因为第一次命令失败、单个旧引用、样式扫描命中、组件 prop 差异或一次浏览器警告就结束任务。只有在当前工作区不是目标业务项目、缺少用户必须提供的授权/外部权限、涉及无法确定的业务协议,或完成修复和重试后仍存在真实阻塞时,才暂停并报告;暂停时必须列出已尝试的修复和剩余阻塞。
## 2. 必须先审计再迁移
...
...
@@ -81,16 +92,9 @@ NODE
先从当前后端配置和 user.applications
[]
读取真实应用名称、稳定标识、授权名称和 basePath,不得猜测或复制名称。
完整实施功能 1–5 的应用只有:
1.
问题整改
2.
审计项目管理
3.
警示案例库
4.
廉洁从业管理
5.
廉洁风险防控
6.
党风廉政建设
项目既定的六应用白名单继续决定功能范围:属于该白名单的目标应用实施完整功能 1–5;不属于该白名单的目标应用只实施功能 4“消息通知”。白名单属于业务范围配置,不是视觉基准;不得从任何其他项目复制应用名单、权限或业务代码。若目标项目文档未明确其归属,先报告“功能范围未确认”,不要擅自加入 shortTitle、视图权限或材料中心文件功能。
其余鑫元应用只实施功能 4“消息通知”,禁止顺带加入 shortTitle、视图权限或材料中心文件功能。每个应用必须有自己的稳定 APPLICATION_NAME、展示名称、授权名称、basePath 和 source_app;禁止复制 problem_rectification_new、
audit_project_manager_new 或任何其他应用标识。
每个应用必须有自己的稳定 APPLICATION_NAME、展示名称、授权名称、basePath 和 source_app;禁止复制
audit_project_manager_new 或任何其他应用标识。
## 4. 依赖和架构边界
...
...
@@ -153,7 +157,8 @@ NODE
### 5.7 ECharts
-
所有图表只使用 echarts + echarts-for-react + 共享 XinyuanEChart;HeroUI Pro 只负责外围 Card、布局和 KPI。
-
图表颜色使用主题中的 16 个鲜艳且稳定的 --xinyuan-chart-
*
Token,和 UI danger/success/warning 分离;严谨业务界面不使用粉色/玫红危险色,红系使用鑫元红。
-
图表颜色使用主题中的 16 个鲜艳且稳定的 --xinyuan-chart-
*
Token,首轮色固定按红→粉→橙→黄→蓝→紫→青→中性灰排列,第 9-16 位只作明暗补充,和 UI danger/success/warning 分离;红色保持鑫元品牌主色,粉色仅作为图表分类色使用。饼图/环图统一使用
`padAngle: 1`
、2px Surface 色间隙和
`borderRadius: 10`
,间隙色读取
`--xinyuan-chart-sector-gap`
,圆角值读取
`--xinyuan-chart-sector-radius`
,图表模块外层遵循 24px 圆角。
-
同一图表的相邻分类按业务展示顺序连续使用邻近色相;有显式业务顺序时传入稳定顺序,无显式顺序时按稳定 key 确定性分配。禁止在有业务顺序时使用名称哈希把相邻扇区/图例打散为跳色色系,筛选、排序和 Tab 切换后已有 key 保持原色。
-
共享适配器统一负责轴、网格、图例、ARIA、resize、globalout、HTML Tooltip、appendToBody、confine 和主题字体;页面只提供真实业务数据与 option。
-
饼图/环图外部标签必须使用 ECharts 原生 label/labelLine,标签显示“分类名称 / 真实数量”两行,引导线短而完整,标签锚定到对应引导线终点,不得错位或拉到卡片边缘。
-
同一可见业务区域的同类图表在 1280px 以上成 1fr / 1fr,单图跨满;移动端单列。折线必须对准其业务文案,主文案明显、辅助文案弱化,线条长度适中。
...
...
@@ -177,7 +182,7 @@ settings.shortTitle === true 只隐藏当前 Grid View 的 title 展示列;不
### 功能 4:消息通知(所有鑫元应用)
-
使用平台原通知接口和
问题整改
同等行为,新增独立 /notifications 页面:消息/待办、全部/未读、搜索、分页、单条已读、全部已读、动态 actions 和关联流程跳转。
-
使用平台原通知接口和
审计项目管理
同等行为,新增独立 /notifications 页面:消息/待办、全部/未读、搜索、分页、单条已读、全部已读、动态 actions 和关联流程跳转。
-
Navbar 使用 Badge.Anchor + Badge + Button + Tooltip,36px Bell;未读 0 隐藏,1–99 真实显示,100+ 显示 99+。Sidebar 不加通知入口。
-
保留目标应用 basePath。站内链接先去除自身 basePath 交给 Umi;外部链接使用新窗口;通知正文按纯文本渲染,不执行 HTML。
...
...
@@ -194,7 +199,7 @@ settings.shortTitle === true 只隐藏当前 Grid View 的 title 展示列;不
## 8. 浏览器验收(必须真实执行)
使用 $playwright-cli 启动目标应用,在相同视口逐项对照审计项目管理
和问题整改
:
使用 $playwright-cli 启动目标应用,在相同视口逐项对照审计项目管理:
-
1440x900、1280x720、768x1024、390x844;浅色内容与固定深色 Sidebar。
-
登录、真实验证码、退出、Sidebar 展开/真 offcanvas、Navbar、应用切换 Modal、通栏搜索、应用卡片和外链。
...
...
docs/xinyuan-design-system.md
View file @
190e6b24
...
...
@@ -166,14 +166,24 @@ Inter 与系统回退字体之间切换。
-
详情和关联记录中的历史数组字符串必须先解析再展示:数组值使用业务标签以“、”连接;流程图/文档结构等结构化对象展示节点、连线、章节和内容块摘要;无法解析出名称的内部 ID 显示“已关联记录/已关联 N 项”,禁止把 JSON、ObjectId 或存储字段原文直接暴露给业务人员。编辑态 JSON 输入仍保持原数据协议。
-
数字指标使用 Pro KPI;所有图表统一通过共享
`XinyuanEChart`
使用
`echarts`
与
`echarts-for-react`
。系列色、坐标轴、网格、图例、Tooltip Surface/边框/阴影均读取
`theme.css`
的
`--xinyuan-chart-*`
Token。当前主题固定提供 16 个鲜艳且稳定的分类色
(红、粉、橙、黄、绿、青、蓝、靛、紫、品红及中性灰),页面只提供业务数据和图表 option。图标始终使用
`theme.css`
的
`--xinyuan-chart-*`
Token。首轮 8 个色位固定按红→粉→橙→黄→蓝→紫→青→中性灰排列,
让最多 8 个分类拥有清晰且高级的色相差异;第 9-16 位提供对应的明暗补充,页面只提供业务数据和
图表 option。具体色值依次为
`#991b1b`
、
`#db2777`
、
`#ea580c`
、
`#eab308`
、
`#1d4ed8`
、
`#7e22ce`
、
`#0891b2`
、
`#475569`
、
`#dc2626`
、
`#ec4899`
、
`#f97316`
、
`#facc15`
、
`#60a5fa`
、
`#a855f7`
、
`#06b6d4`
、
`#1e293b`
。图标始终使用
`AppIcons`
汇出的 Ant Design Icons,ECharts 不作为图标来源。
-
同一图表的分类色按业务展示顺序连续取用相邻色相;有显式业务顺序时必须传入稳定顺序,
无显式顺序时按稳定 key 确定性分配。禁止在有业务顺序时使用名称哈希打散首轮色板,避免相邻
扇区或相邻图例出现无序跳色色系;筛选、排序和 Tab 切换后已有业务 key 保持原色。
-
环形/饼图需要在图表外展示分类内容时,必须使用 ECharts 原生
`label`
与
`labelLine`
引导线,
使用与标签端点对齐的完整引导线连接对应标签,标签按“分类名称 / 真实数量”分两行显示;分类名称保持
13px/500,数量使用 14px/600;标签位置必须锚定到对应引导线终点,避免自动避让造成错位。
不得把引导线拉到卡片边缘或只保留
底部图例代替内容标注。
-
环形/饼图扇区之间使用统一的紧凑 Surface 色间隙和圆角(
`padAngle: 1`
、
`borderWidth: 2`
、
`borderRadius: 10`
),形成清晰分隔但不改变数据比例;间隙色必须读取
`--xinyuan-chart-sector-gap`
,
圆角值读取
`--xinyuan-chart-sector-radius`
,
随主题 Surface 自动适配。图表外层模块继续使用 24px 共享圆角。
-
严谨业务界面不使用粉色、玫红或洋红危险色;HeroUI
`danger`
/
`danger-soft`
必须继承鑫元红系
`--danger`
Token。图表中的红色序列同样使用红系,不使用粉色替代危险语义。
...
...
docs/xinyuan-ui-audit.md
View file @
190e6b24
...
...
@@ -284,10 +284,13 @@ HeroUI Context。`@heroui/styles@3.2.4` 的两个 pnpm peer 虚拟目录仅分
-
驾驶舱状态饼图和阶段柱图已从 HeroUI Pro/Recharts 切换到 ECharts 6.1.0 与
echarts-for-react 3.0.6。共享
`XinyuanEChart`
统一 ARIA、主题系列色、图例、坐标轴、网格和
body HTML Tooltip;柱宽仍限制为 28px,API、统计口径、项目详情入口和数据结构未改。
-
图表分类色已扩展为
`--xinyuan-chart-1`
至
`--xinyuan-chart-16`
,使用鲜艳固定色值;
通过稳定业务 key 分配颜色,禁止页面写入随机或局部色值。
-
图表分类色已扩展为
`--xinyuan-chart-1`
至
`--xinyuan-chart-16`
,使用鲜艳固定色值,首轮顺序固定为
红→粉→橙→黄→蓝→紫→青→中性灰;
通过稳定业务顺序/业务 key 分配相邻色相,禁止页面写入随机或局部色值;项目状态分布按
计划、执行、归档、整改、待启动、完成的顺序连续取用色板,筛选后 key 颜色保持不变。
-
状态环图已启用 ECharts 外部分类标签和
`labelLine`
引导线,标签显示真实状态与数量,
使用
`labelLayout`
根据
`labelLinePoints`
将标签锚定到各自折线终点,避免文案与折线错位。
-
状态环图扇区统一使用
`padAngle: 1`
、2px Surface 色间隙和
`borderRadius: 10`
,扇区边界紧凑清晰且不改变真实数量比例;图表模块外层使用 24px 圆角。
-
删除、拒绝和危险操作的
`danger-soft`
背景已从默认粉色修正为鑫元红系,活动页面不再出现
粉色危险操作视觉。
-
列表普通业务单元格已关闭 Hover 文案 Tooltip;操作列仍保留查看、编辑、删除等真实操作按钮
...
...
src/components/XinyuanEChart.jsx
View file @
190e6b24
...
...
@@ -59,6 +59,23 @@ export default function XinyuanEChart({
const
themedOption
=
useMemo
(()
=>
{
const
theme
=
getXinyuanEChartsTheme
();
const
applyPieTheme
=
(
series
)
=>
{
if
(
series
?.
type
!==
'pie'
)
return
series
;
return
{
...
series
,
itemStyle
:
{
borderColor
:
theme
.
sectorGap
,
borderRadius
:
theme
.
sectorRadius
,
borderWidth
:
2
,
...
series
.
itemStyle
,
},
padAngle
:
series
.
padAngle
??
1
,
};
};
const
themedSeries
=
Array
.
isArray
(
option
?.
series
)
?
option
.
series
.
map
(
applyPieTheme
)
:
applyPieTheme
(
option
?.
series
);
return
{
animationDuration
:
320
,
...
...
@@ -76,6 +93,7 @@ export default function XinyuanEChart({
...
option
?.
textStyle
,
},
...
option
,
series
:
themedSeries
,
legend
:
option
?.
legend
?
{
icon
:
'circle'
,
itemHeight
:
8
,
...
...
src/design-system/chartPalette.js
View file @
190e6b24
...
...
@@ -37,27 +37,59 @@ function hashChartKey(key) {
);
}
export
function
createXinyuanChartColorMap
(
keys
=
[])
{
const
stableKeys
=
[...
new
Set
(
keys
.
map
(
normalizeChartKey
).
filter
(
Boolean
))]
.
sort
();
export
function
createXinyuanChartColorMap
(
keys
=
[],
options
=
{})
{
const
sourceKeys
=
Array
.
isArray
(
keys
)
?
keys
:
[];
const
order
=
Array
.
isArray
(
options
?.
order
)
?
options
.
order
:
[];
const
orderedKeys
=
[...
new
Set
(
sourceKeys
.
map
(
normalizeChartKey
).
filter
(
Boolean
))];
const
preferredOrder
=
new
Map
(
order
.
map
(
normalizeChartKey
).
filter
(
Boolean
).
map
((
key
,
index
)
=>
[
key
,
index
]),
);
const
stableKeys
=
orderedKeys
.
sort
((
left
,
right
)
=>
{
const
leftOrder
=
preferredOrder
.
has
(
left
)
?
preferredOrder
.
get
(
left
)
:
Number
.
MAX_SAFE_INTEGER
;
const
rightOrder
=
preferredOrder
.
has
(
right
)
?
preferredOrder
.
get
(
right
)
:
Number
.
MAX_SAFE_INTEGER
;
if
(
leftOrder
!==
rightOrder
)
{
return
leftOrder
-
rightOrder
;
}
return
left
.
localeCompare
(
right
,
'zh-CN'
);
});
const
unknownPositions
=
new
Map
(
stableKeys
.
filter
((
key
)
=>
!
preferredOrder
.
has
(
key
))
.
map
((
key
,
index
)
=>
[
key
,
index
]),
);
const
colorMap
=
new
Map
();
const
usedIndexes
=
new
Set
();
stableKeys
.
forEach
((
key
,
keyIndex
)
=>
{
const
preferredIndex
=
hashChartKey
(
key
)
%
XINYUAN_CHART_PALETTE
.
length
;
let
paletteIndex
=
preferredIndex
;
stableKeys
.
forEach
((
key
)
=>
{
const
hasExplicitOrder
=
preferredOrder
.
size
>
0
;
let
paletteIndex
=
hasExplicitOrder
&&
preferredOrder
.
has
(
key
)
?
preferredOrder
.
get
(
key
)
%
XINYUAN_CHART_PALETTE
.
length
:
hasExplicitOrder
?
preferredOrder
.
size
+
unknownPositions
.
get
(
key
)
:
hashChartKey
(
key
)
%
XINYUAN_CHART_PALETTE
.
length
;
if
(
keyIndex
<
XINYUAN_CHART_PALETTE
.
length
)
{
if
(
paletteIndex
>=
XINYUAN_CHART_PALETTE
.
length
||
usedIndexes
.
has
(
paletteIndex
)
)
{
const
preferredIndex
=
hashChartKey
(
key
)
%
XINYUAN_CHART_PALETTE
.
length
;
paletteIndex
=
preferredIndex
;
for
(
let
offset
=
0
;
offset
<
XINYUAN_CHART_PALETTE
.
length
;
offset
+=
1
)
{
const
candidateIndex
=
(
preferredIndex
+
offset
)
%
XINYUAN_CHART_PALETTE
.
length
;
if
(
!
usedIndexes
.
has
(
candidateIndex
))
{
paletteIndex
=
candidateIndex
;
usedIndexes
.
add
(
candidateIndex
);
break
;
}
}
}
usedIndexes
.
add
(
paletteIndex
);
colorMap
.
set
(
key
,
XINYUAN_CHART_PALETTE
[
paletteIndex
]);
});
...
...
@@ -79,9 +111,9 @@ export function resolveXinyuanChartColor(color, fallback = '') {
return
match
?
readRootToken
(
match
[
1
],
fallback
)
:
String
(
color
||
fallback
);
}
export
function
createResolvedXinyuanChartColorMap
(
keys
=
[])
{
export
function
createResolvedXinyuanChartColorMap
(
keys
=
[]
,
options
=
{}
)
{
return
new
Map
(
Array
.
from
(
createXinyuanChartColorMap
(
keys
)).
map
(([
key
,
color
])
=>
[
Array
.
from
(
createXinyuanChartColorMap
(
keys
,
options
)).
map
(([
key
,
color
])
=>
[
key
,
resolveXinyuanChartColor
(
color
),
]),
...
...
@@ -104,6 +136,10 @@ export function getXinyuanEChartsTheme() {
)),
tooltipBackground
:
readRootToken
(
'--xinyuan-chart-tooltip-background'
,
'#ffffff'
),
tooltipBorder
:
readRootToken
(
'--xinyuan-chart-tooltip-border'
,
'#dedede'
),
sectorGap
:
readRootToken
(
'--xinyuan-chart-sector-gap'
,
'#ffffff'
),
sectorRadius
:
Number
.
parseFloat
(
readRootToken
(
'--xinyuan-chart-sector-radius'
,
'10'
),
)
||
10
,
tooltipShadow
:
readRootToken
(
'--xinyuan-chart-tooltip-shadow'
,
'0 16px 40px rgb(15 23 42 / 14%)'
,
...
...
src/design-system/shell.css
View file @
190e6b24
...
...
@@ -435,6 +435,23 @@
gap
:
var
(
--rc-page-module-gap
);
}
.rc-section-title
{
margin
:
0
;
color
:
var
(
--rc-text-primary
);
font-size
:
1.25rem
;
font-weight
:
var
(
--rc-font-semibold
);
line-height
:
1.75rem
;
letter-spacing
:
0
;
}
.rc-module-title
{
color
:
var
(
--rc-text-primary
);
font-size
:
1.125rem
;
font-weight
:
var
(
--rc-font-semibold
);
line-height
:
1.5rem
;
letter-spacing
:
0
;
}
.rc-page-grid
{
min-width
:
0
;
gap
:
var
(
--rc-page-module-gap
);
...
...
src/design-system/theme.css
View file @
190e6b24
...
...
@@ -70,22 +70,26 @@
* Ant Design remains the icon source. Resolve these CSS variables to
* concrete colors before assigning them to an ECharts option object.
*/
--xinyuan-chart-1
:
#d92d20
;
--xinyuan-chart-2
:
#ef4444
;
--xinyuan-chart-3
:
#f97316
;
--xinyuan-chart-4
:
#f59e0b
;
--xinyuan-chart-5
:
#22c55e
;
--xinyuan-chart-6
:
#14b87a
;
--xinyuan-chart-7
:
#06b6d4
;
--xinyuan-chart-8
:
#0ea5e9
;
--xinyuan-chart-9
:
#3b82f6
;
--xinyuan-chart-10
:
#6366f1
;
--xinyuan-chart-11
:
#8b5cf6
;
--xinyuan-chart-12
:
#7c3aed
;
--xinyuan-chart-13
:
#b42318
;
--xinyuan-chart-14
:
#84cc16
;
--xinyuan-chart-15
:
#a855f7
;
--xinyuan-chart-16
:
#64748b
;
/* First pass: red -> pink -> orange -> yellow -> blue -> purple -> cyan -> neutral. */
--xinyuan-chart-1
:
#991b1b
;
--xinyuan-chart-2
:
#db2777
;
--xinyuan-chart-3
:
#ea580c
;
--xinyuan-chart-4
:
#eab308
;
--xinyuan-chart-5
:
#1d4ed8
;
--xinyuan-chart-6
:
#7e22ce
;
--xinyuan-chart-7
:
#0891b2
;
--xinyuan-chart-8
:
#475569
;
/* Second pass: stronger/lighter companions for charts with more series. */
--xinyuan-chart-9
:
#dc2626
;
--xinyuan-chart-10
:
#ec4899
;
--xinyuan-chart-11
:
#f97316
;
--xinyuan-chart-12
:
#facc15
;
--xinyuan-chart-13
:
#60a5fa
;
--xinyuan-chart-14
:
#a855f7
;
--xinyuan-chart-15
:
#06b6d4
;
--xinyuan-chart-16
:
#1e293b
;
--xinyuan-chart-sector-gap
:
var
(
--surface
);
--xinyuan-chart-sector-radius
:
10px
;
--xinyuan-chart-grid
:
#e8e8e8
;
--xinyuan-chart-axis
:
#737373
;
--xinyuan-chart-label
:
#737373
;
...
...
src/design-system/tokens.css
View file @
190e6b24
...
...
@@ -165,10 +165,10 @@
--rc-chart-15
:
var
(
--xinyuan-chart-15
);
--rc-chart-16
:
var
(
--xinyuan-chart-16
);
--rc-chart-primary
:
var
(
--rc-chart-1
);
--rc-chart-risk
:
oklch
(
47%
0.145
27.03
);
--rc-chart-warning
:
var
(
--rc-chart-
6
);
--rc-chart-positive
:
var
(
--rc-chart-
2
);
--rc-chart-comparison
:
var
(
--rc-chart-
4
);
--rc-chart-risk
:
var
(
--rc-chart-1
);
--rc-chart-warning
:
var
(
--rc-chart-
3
);
--rc-chart-positive
:
var
(
--rc-chart-
7
);
--rc-chart-comparison
:
var
(
--rc-chart-
5
);
--rc-chart-neutral
:
var
(
--rc-chart-8
);
--rc-chart-legend-font-size
:
var
(
--xinyuan-chart-legend-font-size
);
--rc-chart-legend-line-height
:
var
(
--xinyuan-chart-legend-line-height
);
...
...
src/pages/project_manager_xy/AuditProjectDashboardPage.jsx
View file @
190e6b24
...
...
@@ -34,6 +34,13 @@ const STATUS_TONES = {
归档
:
'secondary'
,
};
const
STATUS_CHART_ORDER
=
[
'计划'
,
'执行'
,
'归档'
,
'整改'
,
'待启动'
,
'完成'
,
'未设置'
];
function
getStatusChartOrder
(
status
)
{
const
index
=
STATUS_CHART_ORDER
.
indexOf
(
status
);
return
index
===
-
1
?
Number
.
MAX_SAFE_INTEGER
:
index
;
}
function
MetricCard
({
label
,
value
,
icon
:
Icon
,
tone
,
onPress
})
{
const
numericValue
=
Number
.
parseFloat
(
String
(
value
).
replace
(
/
[
% ,
]
/g
,
''
));
const
content
=
(
...
...
@@ -93,7 +100,7 @@ function ProjectPanel({ title, records, emptyText, onOpen }) {
return
(
<
Card
className=
"rc-dashboard-card"
>
<
Card
.
Header
className=
"flex-row items-center gap-3"
>
<
Card
.
Title
className=
"min-w-0 flex-1"
>
{
title
}
</
Card
.
Title
>
<
Card
.
Title
className=
"
rc-module-title
min-w-0 flex-1"
>
{
title
}
</
Card
.
Title
>
</
Card
.
Header
>
<
Card
.
Content
className=
"max-h-80 overflow-y-auto"
>
<
ListView
...
...
@@ -123,6 +130,7 @@ function StatusChart({ data }) {
const
theme
=
getXinyuanEChartsTheme
();
const
colorMap
=
createResolvedXinyuanChartColorMap
(
data
.
map
((
item
)
=>
item
.
name
),
{
order
:
STATUS_CHART_ORDER
},
);
return
{
...
...
@@ -132,7 +140,9 @@ function StatusChart({ data }) {
},
series
:
[{
avoidLabelOverlap
:
true
,
data
:
data
.
map
((
item
)
=>
({
data
:
[...
data
].
sort
(
(
left
,
right
)
=>
getStatusChartOrder
(
left
.
name
)
-
getStatusChartOrder
(
right
.
name
),
).
map
((
item
)
=>
({
...
item
,
itemStyle
:
{
color
:
colorMap
.
get
(
item
.
name
)
},
})),
...
...
@@ -355,21 +365,21 @@ export default function AuditProjectDashboardPage() {
</
section
>
<
section
className=
"rc-page-section"
>
<
h2
className=
"
text-base font-medium text-foreground
"
>
项目进度分析
</
h2
>
<
h2
className=
"
rc-section-title
"
>
项目进度分析
</
h2
>
<
div
className=
"rc-page-grid rc-chart-grid"
>
<
Card
className=
"rc-dashboard-card"
>
<
Card
.
Header
><
Card
.
Title
>
项目状态分布
</
Card
.
Title
></
Card
.
Header
>
<
Card
.
Header
><
Card
.
Title
className=
"rc-module-title"
>
项目状态分布
</
Card
.
Title
></
Card
.
Header
>
<
Card
.
Content
>
{
dashboard
.
statusData
.
length
?
<
StatusChart
data=
{
dashboard
.
statusData
}
/>
:
null
}
</
Card
.
Content
>
</
Card
>
<
Card
className=
"rc-dashboard-card"
>
<
Card
.
Header
><
Card
.
Title
>
开展中项目进度
</
Card
.
Title
></
Card
.
Header
>
<
Card
.
Header
><
Card
.
Title
className=
"rc-module-title"
>
开展中项目进度
</
Card
.
Title
></
Card
.
Header
>
<
Card
.
Content
><
StageChart
data=
{
dashboard
.
stageData
}
/></
Card
.
Content
>
</
Card
>
</
div
>
</
section
>
<
section
className=
"rc-page-section"
>
<
h2
className=
"
text-base font-medium text-foreground
"
>
项目提醒
</
h2
>
<
h2
className=
"
rc-section-title
"
>
项目提醒
</
h2
>
<
div
className=
"grid gap-6 xl:grid-cols-3"
>
<
ProjectPanel
title=
"逾期未完成项目"
records=
{
dashboard
.
overdue
}
emptyText=
"暂无逾期未完成项目"
onOpen=
{
openRecord
}
/>
<
ProjectPanel
title=
"正在开展项目"
records=
{
dashboard
.
active
}
emptyText=
"暂无正在开展项目"
onOpen=
{
openRecord
}
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment