Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
I
incorrupt_party_build
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
incorrupt_party_build
Commits
bdb1a4a7
Commit
bdb1a4a7
authored
Sep 03, 2026
by
Andy-bubu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: polish integrity party interactions
parent
e31e7c18
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
100 additions
and
50 deletions
+100
-50
ui-architecture.md
docs/ui-architecture.md
+3
-1
ui-migration-checklist.md
docs/ui-migration-checklist.md
+3
-1
xinyuan-design-system.md
docs/xinyuan-design-system.md
+3
-1
shell.css
src/design-system/shell.css
+4
-1
index.jsx
src/pages/project_manager_xy/integrity-party/index.jsx
+87
-46
No files found.
docs/ui-architecture.md
View file @
bdb1a4a7
...
...
@@ -49,7 +49,8 @@
Native HeroUI 静态架构门禁已通过:
`src/xinyuan-portable.css`
已移除,业务图表统一保留并使用 ECharts 适配器,页面目录无私有 CSS/Less/SCSS;仅保留经确认的共享样式层。HeroUI 与 HeroUI Pro 的样式分别通过
`@heroui/styles/css`
和
`@heroui-pro/react/css`
显式加载;包根
`@heroui/styles`
是 JavaScript 样式工具入口,不能替代 CSS 入口。当前品牌主色固定为
`#DA241A`
,HeroUI
`accent/focus`
和
`primary-*`
Token 不随浅深主题改变色相;图表 Token 按品牌红深浅、暖土色、中性灰紫和灰蓝分组,禁止绿色和荧光色。2026-08-26 已完成四视口、深浅主题、权限、通知和文件事务的运行态浏览器门禁。
# 共享 UI 架构补充
`XinyuanEChart`
是图表唯一渲染适配器,页面仅提供业务数据和 ECharts option;适配器统一主题、Tooltip、坐标轴和 Pie 扇区样式。相同分类维度的多个数据项使用
`createResolvedXinyuanChartColorMap`
和
`XINYUAN_CHART_CATEGORY_PALETTE`
按稳定顺序分配颜色,顺序为品牌红深浅 → 暖土色 → 中性灰紫 → 灰蓝,禁止绿色、荧光色和彩虹式跳色;单一指标或多指标系列使用
`XINYUAN_CHART_SEMANTIC`
语义色,单系列固定使用
`#DA241A`
,页面不得写入硬编码颜色。业务源码禁止直接导入 Recharts 或 HeroUI Pro 图表组件;
`recharts`
依赖仅因当前 HeroUI Pro
`KPI`
包的静态运行时解析而保留,不作为应用图表渲染器。
`XinyuanModal`
统一使用
`bg-background`
Dialog Surface。列表分页由
`DataTablePagination`
统一承载容量选择器与页码状态:容量使用 HeroUI Autocomplete 受控单选,标准选项为
`20 / 50 / 100 条/页`
、默认值必须属于选项集合,固定少量选项时关闭
`showSearch`
与
`isClearable`
,切换容量回到第 1 页。
`XinyuanEChart`
是图表唯一渲染适配器,页面仅提供业务数据和 ECharts option;适配器统一主题、Tooltip、坐标轴和 Pie 扇区样式。相同分类维度的多个数据项使用
`createResolvedXinyuanChartColorMap`
和
`XINYUAN_CHART_CATEGORY_PALETTE`
按稳定顺序分配颜色,顺序为品牌红深浅 → 暖土色 → 中性灰紫 → 灰蓝,禁止绿色、荧光色和彩虹式跳色;单一指标或多指标系列使用
`XINYUAN_CHART_SEMANTIC`
语义色,单系列固定使用
`#DA241A`
,页面不得写入硬编码颜色。业务源码禁止直接导入 Recharts 或 HeroUI Pro 图表组件;
`recharts`
依赖仅因当前 HeroUI Pro
`KPI`
包的静态运行时解析而保留,不作为应用图表渲染器。
`XinyuanModal`
统一使用
`bg-background`
Dialog Surface。党风廉政台账筛选由 HeroUI
`form`
手动提交,字段值先保留在页面草稿,右侧操作固定为重置图标、
`查询`
主按钮和
`展开/收起`
Disclosure;查询时复用原有
`reload`
请求参数,不改变接口协议。列表分页由
`DataTablePagination`
统一承载容量选择器与页码状态:容量使用 HeroUI Autocomplete 受控单选,标准选项为
`20 / 50 / 100 条/页`
、默认值必须属于选项集合,固定少量选项时关闭
`showSearch`
与
`isClearable`
,切换容量回到第 1 页。
长列表 DataGrid 的
`.data-table-scroll`
只隔离横向滚动;纵向在首行/末行继续滚动时必须允许滚动链传递到
`.app-shell-content-scroll`
,保证筛选、列表和 Pagination 可以连续浏览,不增加页面级滚轮监听或改变数据请求时机。
驾驶舱模块标题沿用“审计项目管理”基准的 HeroUI
`Card.Header`
左对齐横向结构;
`Card.Title`
使用共享
`.rc-module-title`
(16px/600、24px 行高、主题前景色)与
`min-w-0 flex-1 text-left`
,操作或描述信息放在标题右侧,不通过页面私有 CSS 改写字号、颜色或字重。
...
...
@@ -58,3 +59,4 @@ Native HeroUI 静态架构门禁已通过:`src/xinyuan-portable.css` 已移除
台账详情预览使用固定功能标题,记录标题作为正文首项展示;编辑态在同一位置使用 HeroUI
`Input`
修改顶层
`record.title`
,不改变
`metadata`
。标题展示尊重当前 View 的
`shortTitle`
配置。
详情弹窗结构固定为 HeroUI
`Modal.Root > Modal.Backdrop > Modal.Container > Modal.Dialog`
。字段控件直接来自
`@heroui/react`
(
`Input`
、
`TextArea`
、
`DatePicker`
、
`Autocomplete`
)或
`@heroui-pro/react`
(
`DropZone`
);预览态使用静态只读值,编辑态使用
`secondary`
控件,权限禁用字段不显示灰色伪控件。不得引入 Catalyst、Headless UI、原生表单控件或自制 Modal/字段外观。
预览态底部仅显示
`primary`
编辑按钮作为主操作;点击后通过同一 Modal 内的状态切换进入编辑态,不重建记录或材料会话。编辑态底部显示
`secondary`
取消与
`primary`
保存,取消关闭弹窗且不触发保存。
docs/ui-migration-checklist.md
View file @
bdb1a4a7
...
...
@@ -17,10 +17,12 @@
-
[
x
]
Shell:迁移品牌、offcanvas、用户菜单、主题和 base-aware 导航
-
[
x
]
应用切换:同步
`model_analysis`
HeroUI Modal、
`site.group`
动态分组、真实数量、“其他应用”/“全部应用”回退和 36px identity well
-
[
x
]
驾驶舱:KPI 使用 HeroUI Pro KPI compound API,所有业务图表统一通过共享
`XinyuanEChart`
(ECharts)适配器渲染
-
[
x
]
党风廉政 Tabs、结构化筛选与透明工具栏 SearchField;
无刷新/查询按钮并保持自动筛选
-
[
x
]
党风廉政 Tabs、结构化筛选与透明工具栏 SearchField;
结构化筛选按基准使用重置图标、查询按钮和 Disclosure 手动提交,关键词搜索保持原有延迟
-
[
x
]
党风廉政 DataGrid、选择、ActionBar、20/50/100 页容量 Pagination;默认 20,切换后回到第 1 页且无清除图标/搜索框
-
[
x
]
长列表滚动边界:DataGrid 到达首/末行后继续纵向滚动可自然传递至页面,底部 Pagination 可达;横向滚动仍限制在列表内
-
[
x
]
新建/编辑、导入、批量修改、删除确认 Modal
-
[
x
]
详情预览/编辑遵循 HeroUI Modal:预览使用固定功能标题 + 正文记录标题静态值,编辑使用 HeroUI Input 修改顶层
`record.title`
;权限禁用字段保持只读值,不以灰色控件冒充预览
-
[
x
]
详情预览态通过同一 Modal 的
`primary`
编辑按钮平滑切换编辑态;编辑态显示取消/保存,保留字段与材料草稿,取消不保存
-
[
x
]
DropZone 上传、附件维护、Pro DataGrid Excel 预览
## 业务回归
...
...
docs/xinyuan-design-system.md
View file @
bdb1a4a7
...
...
@@ -30,8 +30,9 @@
-
Shell:240px offcanvas Sidebar、64px Navbar、桌面/平板/手机分别使用 48/32/16px 对称 gutter。
-
列表顺序:页面 Tabs、结构化筛选 Surface、透明数据集标题与工具栏、DataGrid、Pagination。
-
筛选 Surface 最多首显三个结构化字段,溢出字段通过 HeroUI Disclosure 展开
;不显示刷新或查询按钮,字段变化自动筛选,关键词 SearchField
约 300ms 延迟。
-
筛选 Surface 最多首显三个结构化字段,溢出字段通过 HeroUI Disclosure 展开
。党风廉政台账使用手动提交模式:右侧依次提供 HeroUI 重置图标按钮、
`查询`
主按钮和
`展开/收起`
Disclosure 触发器;字段变化只更新筛选草稿,点击查询才复用原有请求回调。列表工具栏关键词 SearchField 保持原有
约 300ms 延迟。
-
业务列表使用 HeroUI Pagination,并在列表总数信息旁提供页容量选择器;当前标准选项为
`20 / 50 / 100 条/页`
,默认值必须是选项中的一个(本应用默认
`20`
)。切换页容量时回到第 1 页,并复用原有查询回调传递新的
`pageSize`
。
-
长列表的数据区域使用独立纵向滚动和 sticky 表头;纵向滚动到首行/末行后继续滚动时,滚动链自然交给页面容器,使底部 Pagination 或顶部筛选可达。横向滚动仍限制在 DataGrid 内,不影响页面横向布局。
-
普通业务单选使用 HeroUI Autocomplete 的受控单选结构,已有值时显示官方
`Autocomplete.ClearButton`
;页容量选择器属于例外,选项数量较少且固定时必须传
`showSearch={false}`
和
`isClearable={false}`
,不渲染“输入关键词搜索”框,也不显示清除/删除图标。选择器只能切换有效页容量,不能提交空值。
-
页容量选择器保留加载禁用状态、当前值回显和
`20 / 50 / 100`
的顺序;页面不得把不存在的值(例如
`10`
)作为初始
`pageSize`
或展示文本。
-
Dashboard/KPI 外层圆角 24px,DataGrid 20px,字段 12px,Modal 24px。
...
...
@@ -40,6 +41,7 @@
-
台账详情预览弹窗的 Modal Heading 使用固定功能标题(如“预览台账记录”),正文首项按当前 View 的 title 配置展示“记录标题”;编辑态该项使用 HeroUI
`Input`
编辑并仅写入顶层
`record.title`
,不得写入
`metadata`
。标题展示沿用
`displayTitle`
去除自动生成的日期后缀;
`shortTitle`
隐藏时同步隐藏该正文项。
-
预览态普通标量字段使用无边框静态值:标签为
`text-muted`
,值为
`text-foreground`
,空值显示“暂无内容”;不得用灰色 disabled Input/Autocomplete 冒充预览。编辑态才显示 HeroUI
`secondary`
控件;权限禁用、锁定或只读字段在同一网格中继续显示静态只读值。
-
预览与编辑共用两列字段网格和字段顺序;长文本、附件等内容跨两列。编辑态使用 Footer 的 HeroUI
`secondary`
取消 +
`primary`
保存,保存只提交一次,取消丢弃草稿,不改变原有校验、权限和请求时机。
-
预览态 Footer 使用 HeroUI
`primary`
编辑按钮作为主操作;点击后在同一个 Modal 和编辑会话内切换为编辑态,保留当前记录标题、字段草稿和材料草稿,不关闭后重新打开;进入编辑态后显示
`secondary`
取消 +
`primary`
保存,取消关闭并丢弃未保存草稿。
-
例行成功反馈使用顶部居中的自动消失 Toast;需要处理的错误保留上下文 Alert。
-
应用切换严格继承
`model_analysis`
:从
`/info -> site.group`
动态生成分组,保持配置顺序并显示真实数量;未归组应用进入“其他应用”,无配置时使用“全部应用”。Modal 固定 46rem/42rem、28px inset、手机一列、
`sm`
起两列,间距 12px;加载骨架使用相同网格,桌面不得切成三列,长列表仅在 Modal Body 内滚动。
...
...
src/design-system/shell.css
View file @
bdb1a4a7
...
...
@@ -723,7 +723,10 @@
max-height
:
min
(
60
dvh
,
42rem
);
overflow-x
:
auto
;
overflow-y
:
auto
;
overscroll-behavior
:
contain
;
/* Keep horizontal gestures inside the grid, but hand vertical wheel/touch
momentum to the page once the first or last row has been reached. */
overscroll-behavior-x
:
contain
;
overscroll-behavior-y
:
auto
;
}
/* DataGrid adds a non-scrolling resize wrapper. Let sticky headers use the
...
...
src/pages/project_manager_xy/integrity-party/index.jsx
View file @
bdb1a4a7
import
{
ArrowPathIcon
,
Close
,
ChevronDownIcon
,
Delete
,
...
...
@@ -26,6 +27,7 @@ import {
SearchField
,
Surface
,
Tabs
,
Tooltip
,
TextArea
,
Toast
,
}
from
'@heroui/react'
;
...
...
@@ -479,13 +481,10 @@ export default function IntegrityPartyPage() {
}
useEffect
(()
=>
{
const
timer
=
window
.
setTimeout
(()
=>
{
reload
(
0
,
filters
[
activeKey
]);
},
300
);
return
()
=>
window
.
clearTimeout
(
timer
);
reload
(
0
,
filters
[
activeKey
]);
// 筛选字段是待提交草稿,只有 activeKey/view/权限变化时自动加载。
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
activeKey
,
activeViewName
,
canAccessLedger
,
filters
]);
},
[
activeKey
,
activeViewName
,
canAccessLedger
]);
function
updateFilter
(
name
,
value
)
{
setFilters
((
current
)
=>
({
...
...
@@ -498,6 +497,15 @@ export default function IntegrityPartyPage() {
setPage
(
0
);
}
function
clearFilters
()
{
setFilters
((
current
)
=>
({
...
current
,
[
activeKey
]:
createEmptyFilters
(
activeConfig
),
}));
setPage
(
0
);
setSelectedIds
([]);
}
function
openCreateDialog
()
{
pendingLocalMaterialsRef
.
current
=
{};
setDetailSessionId
((
value
)
=>
value
+
1
);
...
...
@@ -889,42 +897,71 @@ export default function IntegrityPartyPage() {
isExpanded=
{
filtersExpanded
}
onExpandedChange=
{
setFiltersExpanded
}
>
<
div
className=
"grid min-w-0 gap-3 xl:grid-cols-[minmax(0,1fr)_auto] xl:items-end"
>
<
div
className=
"grid min-w-0 grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3"
>
{
primaryFilterItems
.
map
((
item
)
=>
(
<
FilterField
key=
{
item
.
key
}
label=
{
item
.
label
}
className=
{
item
.
className
}
>
{
item
.
node
}
</
FilterField
>
))
}
</
div
>
{
expandedFilterItems
.
length
>
0
?
(
<
form
onSubmit=
{
(
event
)
=>
{
event
.
preventDefault
();
reload
(
0
,
filters
[
activeKey
]);
}
}
>
<
div
className=
"grid min-w-0 gap-3 xl:grid-cols-[minmax(0,1fr)_auto] xl:items-end"
>
<
div
className=
"grid min-w-0 grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3"
>
{
primaryFilterItems
.
map
((
item
)
=>
(
<
FilterField
key=
{
item
.
key
}
label=
{
item
.
label
}
className=
{
item
.
className
}
>
{
item
.
node
}
</
FilterField
>
))
}
</
div
>
<
div
className=
"flex min-w-0 flex-wrap items-end gap-2 md:justify-end xl:flex-nowrap"
>
<
Disclosure
.
Trigger
className=
"button button--sm button--ghost"
>
<
span
>
{
filtersExpanded
?
'收起'
:
'展开'
}
</
span
>
<
Disclosure
.
Indicator
>
<
ChevronDownIcon
size=
{
14
}
/>
</
Disclosure
.
Indicator
>
</
Disclosure
.
Trigger
>
<
Tooltip
delay=
{
0
}
>
<
Button
aria
-
label=
"重置筛选"
isDisabled=
{
loading
}
isIconOnly
size=
"sm"
variant=
"secondary"
type=
"button"
onPress=
{
clearFilters
}
>
<
ArrowPathIcon
size=
{
16
}
/>
</
Button
>
<
Tooltip
.
Content
>
重置筛选
</
Tooltip
.
Content
>
</
Tooltip
>
<
Button
isDisabled=
{
loading
}
size=
"sm"
variant=
"primary"
type=
"submit"
>
查询
</
Button
>
{
expandedFilterItems
.
length
>
0
?
(
<
Disclosure
.
Trigger
className=
"button button--sm button--ghost"
>
<
span
>
{
filtersExpanded
?
'收起'
:
'展开'
}
</
span
>
<
Disclosure
.
Indicator
>
<
ChevronDownIcon
aria
-
hidden=
"true"
size=
{
14
}
/>
</
Disclosure
.
Indicator
>
</
Disclosure
.
Trigger
>
)
:
null
}
</
div
>
)
:
null
}
{
expandedFilterItems
.
length
>
0
?
(
<
Disclosure
.
Content
hidden=
{
!
filtersExpanded
}
className=
{
clsx
(
'min-h-0 min-w-0 xl:col-start-1 xl:col-end-2
'
,
!
filtersExpanded
&&
'hidden'
,
)
}
>
<
div
className=
"grid min-w-0 grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3"
>
{
expandedFilterItems
.
map
((
item
)
=>
(
<
FilterField
key=
{
item
.
key
}
label=
{
item
.
label
}
>
{
item
.
node
}
</
FilterField
>
))
}
</
div
>
</
Disclosure
.
Content
>
)
:
null
}
</
div
>
{
expandedFilterItems
.
length
>
0
?
(
<
Disclosure
.
Content
className=
{
clsx
(
'min-w-0 xl:col-start-1 xl:col-end-2'
,
!
filtersExpanded
&&
'hidden
'
,
)
}
>
<
div
className=
"grid min-w-0 grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3"
>
{
expandedFilterItems
.
map
((
item
)
=>
(
<
FilterField
key=
{
item
.
key
}
label=
{
item
.
label
}
>
{
item
.
node
}
</
FilterField
>
))
}
</
div
>
</
Disclosure
.
Content
>
)
:
null
}
</
div
>
</
form
>
</
Disclosure
>
</
XinyuanFilterSurface
>
...
...
@@ -1028,16 +1065,20 @@ export default function IntegrityPartyPage() {
size=
"4xl"
title=
{
detailMode
===
'create'
?
`新建${activeConfig.tabLabel}记录`
:
detailMode
===
'view'
?
'预览台账记录'
:
'编辑台账记录'
}
footer=
{
<>
<
Button
type=
"button"
size=
"sm"
variant=
"
secondary"
onPress=
{
()
=>
handleDetailOpenChange
(
false
)
}
>
取消
detailMode
===
'view'
?
(
<
Button
type=
"button"
size=
"sm"
variant=
"
primary"
onPress=
{
()
=>
setDetailMode
(
'edit'
)
}
>
编辑
</
Button
>
{
detailMode
!==
'view'
?
(
)
:
(
<>
<
Button
type=
"button"
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
handleDetailOpenChange
(
false
)
}
>
取消
</
Button
>
<
Button
type=
"button"
isPending=
{
saving
}
size=
"sm"
variant=
"primary"
onPress=
{
saveDetail
}
>
{
saving
?
'保存中...'
:
'保存'
}
</
Button
>
)
:
null
}
</>
</>
)
}
>
{
detailViews
.
length
>
1
?
(
...
...
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