Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
I
integrity_practice_management_new
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
integrity_practice_management_new
Commits
90949774
Commit
90949774
authored
Sep 03, 2026
by
Andy-bubu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: unify Xinyuan brand and filter visuals
parent
174de5ea
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
205 additions
and
99 deletions
+205
-99
xinyuan-design-system.md
docs/xinyuan-design-system.md
+6
-0
DataTable.jsx
src/components/DataTable.jsx
+1
-1
index.jsx
src/components/record-workbench/index.jsx
+51
-24
chartTokens.js
src/design-system/chartTokens.js
+34
-0
shell.css
src/design-system/shell.css
+25
-1
theme.css
src/design-system/theme.css
+32
-26
tokens.css
src/design-system/tokens.css
+27
-11
useXinyuanChartTheme.js
src/design-system/useXinyuanChartTheme.js
+2
-1
SubjectWorkbench.jsx
src/pages/integrity_practice_management/SubjectWorkbench.jsx
+3
-0
integrityPracticeWorkbenchService.js
..._practice_management/integrityPracticeWorkbenchService.js
+1
-1
index.jsx
src/pages/problem_rectification/dashboard/index.jsx
+23
-34
No files found.
docs/xinyuan-design-system.md
View file @
90949774
...
@@ -13,6 +13,12 @@ Inter 禁止通过 `src/tailwind.css` 导入。Tailwind v4 内容扫描必须排
...
@@ -13,6 +13,12 @@ Inter 禁止通过 `src/tailwind.css` 导入。Tailwind v4 内容扫描必须排
页面
`className`
仅承担 flex、grid、宽度、间距、对齐、滚动和响应式。背景、颜色、描边、圆角、阴影及交互状态由官方 variant、compound API 和上述共享样式负责。
页面
`className`
仅承担 flex、grid、宽度、间距、对齐、滚动和响应式。背景、颜色、描边、圆角、阴影及交互状态由官方 variant、compound API 和上述共享样式负责。
## 品牌与图表色板
-
鑫元品牌主色固定为
`#DA241A`
。HeroUI v3 的
`--accent`
、
`--accent-hover`
、
`--focus`
以及共享
`--rc-brand-primary`
均不得被页面或深色主题改写为其他色相;primary 色阶仅作为兼容别名维护。
-
图表统一使用
`--rc-chart-1`
至
`--rc-chart-16`
,由
`src/design-system/chartTokens.js`
提供 ECharts 的解析值。顺序为品牌红、低饱和暖色、灰紫中性色和蓝灰色,禁止绿色、荧光色和彩虹式相邻对撞;单系列始终使用
`chart-1`
。
-
KPI 图标色调复用同一图表色板的暖色/灰紫/蓝灰衍生值,卡片表面保持中性,不以高饱和渐变区分指标。
## 组件合同
## 组件合同
-
Shell:
`@heroui-pro/react/sidebar`
、
`navbar`
;桌面 offcanvas 真折叠,移动端
`Sidebar.Mobile`
;导航分组首次进入时默认展开,用户仍可手动收起。
-
Shell:
`@heroui-pro/react/sidebar`
、
`navbar`
;桌面 offcanvas 真折叠,移动端
`Sidebar.Mobile`
;导航分组首次进入时默认展开,用户仍可手动收起。
...
...
src/components/DataTable.jsx
View file @
90949774
...
@@ -604,7 +604,7 @@ export function DataTablePagination({
...
@@ -604,7 +604,7 @@ export function DataTablePagination({
{
hasPageSizePicker
?
(
{
hasPageSizePicker
?
(
<
XinyuanAutocomplete
<
XinyuanAutocomplete
aria
-
label=
"每页条数"
aria
-
label=
"每页条数"
className=
"w-
24
shrink-0"
className=
"w-
32
shrink-0"
isDisabled=
{
isDisabled
}
isDisabled=
{
isDisabled
}
options=
{
pageSizeOptionsForPicker
}
options=
{
pageSizeOptionsForPicker
}
placeholder=
"每页条数"
placeholder=
"每页条数"
...
...
src/components/record-workbench/index.jsx
View file @
90949774
import
{
Close
,
Eye
,
More
,
Reload
,
Search
}
from
'@/components/AppIcons'
;
import
{
C
hevronDown
,
C
lose
,
Eye
,
More
,
Reload
,
Search
}
from
'@/components/AppIcons'
;
import
{
TableActionButton
,
TableActionGroup
}
from
'@/components/TableActionButton'
;
import
{
TableActionButton
,
TableActionGroup
}
from
'@/components/TableActionButton'
;
import
FilterSelect
from
'@/components/FilterSelect'
;
import
FilterSelect
from
'@/components/FilterSelect'
;
import
FormDatePicker
from
'@/components/FormDatePicker'
;
import
FormDatePicker
from
'@/components/FormDatePicker'
;
...
@@ -174,6 +174,7 @@ export default function RecordWorkbench({
...
@@ -174,6 +174,7 @@ export default function RecordWorkbench({
filterSchema = EMPTY_ARRAY,
filterSchema = EMPTY_ARRAY,
onFiltersChange,
onFiltersChange,
onClearFilters,
onClearFilters,
onQuery,
title,
title,
listTitle,
listTitle,
columns = EMPTY_ARRAY,
columns = EMPTY_ARRAY,
...
@@ -373,31 +374,57 @@ export default function RecordWorkbench({
...
@@ -373,31 +374,57 @@ export default function RecordWorkbench({
{structuredFilterFields.length > 0 ? (
{structuredFilterFields.length > 0 ? (
<Surface className="rc-filter-surface p-6" variant="default">
<Surface className="rc-filter-surface p-6" variant="default">
<Disclosure isExpanded={filtersExpanded} onExpandedChange={setFiltersExpanded}>
<Disclosure isExpanded={filtersExpanded} onExpandedChange={setFiltersExpanded}>
<div className="grid min-w-0 gap-3 xl:grid-cols-[minmax(0,1fr)_auto] xl:items-end">
<form
<div className="grid min-w-0 gap-3 sm:grid-cols-2 xl:grid-cols-3">
onSubmit={(event) => {
{primaryFilterFields.map(renderFilterField)}
event.preventDefault();
</div>
onQuery?.();
<div className="flex min-w-0 items-end justify-end gap-2">
}}
{onClearFilters ? (
>
<Tooltip delay={0}>
<div className="grid min-w-0 gap-3 xl:grid-cols-[minmax(0,1fr)_auto] xl:items-end">
<Button isIconOnly aria-label="重置筛选" size="sm" variant="ghost" onPress={onClearFilters}><Reload size={16} /></Button>
<div className="grid min-w-0 gap-3 sm:grid-cols-2 xl:grid-cols-3">
<Tooltip.Content>重置筛选</Tooltip.Content>
{primaryFilterFields.map(renderFilterField)}
</Tooltip>
</div>
) : null}
<div className="flex min-w-0 flex-wrap items-end gap-2 md:justify-end xl:flex-nowrap">
{expandedFilterFields.length > 0 ? (
{onClearFilters ? (
<Disclosure.Trigger className={buttonVariants({ size: 'sm', variant: 'ghost' })}>
<Tooltip delay={0}>
<span>{filtersExpanded ? '收起' : '展开'}</span>
<Button
</Disclosure.Trigger>
aria-label="重置筛选"
className="rc-filter-reset-button"
isDisabled={Boolean(states.loading)}
isIconOnly
size="sm"
variant="secondary"
type="button"
onPress={onClearFilters}
>
<Reload size={16} />
</Button>
<Tooltip.Content>重置筛选</Tooltip.Content>
</Tooltip>
) : null}
{onQuery ? (
<Button isDisabled={Boolean(states.loading)} size="sm" variant="primary" type="submit">
查询
</Button>
) : null}
{expandedFilterFields.length > 0 ? (
<Disclosure.Trigger className={buttonVariants({ size: 'sm', variant: 'ghost' })}>
<span>{filtersExpanded ? '收起' : '展开'}</span>
<Disclosure.Indicator>
<ChevronDown aria-hidden="true" size={14} />
</Disclosure.Indicator>
</Disclosure.Trigger>
) : null}
</div>
{expandedFilterFields.length > 0 && filtersExpanded ? (
<Disclosure.Content className="rc-filter-disclosure-content min-w-0 xl:col-start-1 xl:col-end-2">
<div className="grid min-w-0 grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3">
{expandedFilterFields.map(renderFilterField)}
</div>
</Disclosure.Content>
) : null}
) : null}
</div>
</div>
{expandedFilterFields.length > 0 && filtersExpanded ? (
</form>
<Disclosure.Content className="rc-filter-disclosure-content min-w-0 xl:col-start-1 xl:col-end-2">
<div className="grid min-w-0 grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3">
{expandedFilterFields.map(renderFilterField)}
</div>
</Disclosure.Content>
) : null}
</div>
</Disclosure>
</Disclosure>
</Surface>
</Surface>
) : null}
) : null}
...
...
src/design-system/chartTokens.js
0 → 100644
View file @
90949774
/**
* Xinyuan chart palette in visual order: brand red, warm neutrals, mauve
* neutrals, then restrained blue-greys. Green and fluorescent hues are not
* part of the visualization system.
*/
export
const
XINYUAN_CHART_COLORS
=
[
'#DA241A'
,
'#B83A32'
,
'#C95A52'
,
'#D47A70'
,
'#A65A45'
,
'#B87958'
,
'#C99772'
,
'#6F6674'
,
'#807783'
,
'#938B96'
,
'#4F6380'
,
'#61758F'
,
'#74879A'
,
'#8A6F63'
,
'#9A8174'
,
'#B5A69D'
,
];
export
function
getXinyuanChartColors
()
{
if
(
typeof
window
===
'undefined'
)
{
return
XINYUAN_CHART_COLORS
;
}
const
styles
=
getComputedStyle
(
document
.
documentElement
);
return
XINYUAN_CHART_COLORS
.
map
((
fallback
,
index
)
=>
(
styles
.
getPropertyValue
(
`--rc-chart-
${
index
+
1
}
`
).
trim
()
||
fallback
));
}
src/design-system/shell.css
View file @
90949774
...
@@ -552,6 +552,27 @@
...
@@ -552,6 +552,27 @@
border-radius
:
var
(
--rc-radius-overlay
);
border-radius
:
var
(
--rc-radius-overlay
);
}
}
.rc-filter-reset-button.button
{
width
:
2.25rem
;
min-width
:
2.25rem
;
max-width
:
2.25rem
;
height
:
2.25rem
;
flex
:
0
0
2.25rem
;
padding
:
0
;
border-radius
:
999px
;
color
:
var
(
--rc-brand-primary
);
}
.rc-filter-reset-button.button
>
span
,
.rc-filter-reset-button.button
.anticon
,
.rc-filter-reset-button.button
svg
{
display
:
inline-grid
;
width
:
1rem
;
height
:
1rem
;
place-items
:
center
;
margin
:
0
;
}
/* Filter fields paint their HeroUI focus/invalid ring outside the disclosure
/* Filter fields paint their HeroUI focus/invalid ring outside the disclosure
panel. The workbench unmounts this content while the filter is collapsed. */
panel. The workbench unmounts this content while the filter is collapsed. */
.rc-filter-disclosure-content
{
.rc-filter-disclosure-content
{
...
@@ -729,7 +750,10 @@
...
@@ -729,7 +750,10 @@
max-height
:
min
(
60
dvh
,
42rem
);
max-height
:
min
(
60
dvh
,
42rem
);
overflow-x
:
auto
;
overflow-x
:
auto
;
overflow-y
:
auto
;
overflow-y
:
auto
;
overscroll-behavior
:
contain
;
/* Keep horizontal overflow inside the grid, but let vertical wheel/touch
scrolling continue into the page once the last row is reached. */
overscroll-behavior-x
:
contain
;
overscroll-behavior-y
:
auto
;
}
}
/* DataGrid adds a non-scrolling resize wrapper. Let sticky headers use the
/* DataGrid adds a non-scrolling resize wrapper. Let sticky headers use the
...
...
src/design-system/theme.css
View file @
90949774
...
@@ -11,8 +11,11 @@
...
@@ -11,8 +11,11 @@
[
data-theme
=
"light"
],
[
data-theme
=
"light"
],
[
data-theme
=
"default"
]
{
[
data-theme
=
"default"
]
{
/* Theme Colors (Light Mode) */
/* Theme Colors (Light Mode) */
--accent
:
oklch
(
57.14%
0.2156
29.20
);
/* Xinyuan brand red. HeroUI's accent token is the v3 primary color. */
--accent
:
#DA241A
;
--accent-foreground
:
oklch
(
99.11%
0
0
);
--accent-foreground
:
oklch
(
99.11%
0
0
);
--accent-hover
:
#C91F17
;
--accent-pressed
:
#B51B14
;
--background
:
oklch
(
97.02%
0.0000
29.20
);
--background
:
oklch
(
97.02%
0.0000
29.20
);
--border
:
oklch
(
90.00%
0.0000
29.20
);
--border
:
oklch
(
90.00%
0.0000
29.20
);
--danger
:
oklch
(
45.32%
0.1661
27.03
);
--danger
:
oklch
(
45.32%
0.1661
27.03
);
...
@@ -23,7 +26,7 @@
...
@@ -23,7 +26,7 @@
--field-border
:
transparent
;
--field-border
:
transparent
;
--field-foreground
:
oklch
(
21.03%
0.0000
29.20
);
--field-foreground
:
oklch
(
21.03%
0.0000
29.20
);
--field-placeholder
:
oklch
(
55.17%
0.0000
29.20
);
--field-placeholder
:
oklch
(
55.17%
0.0000
29.20
);
--focus
:
oklch
(
57.14%
0.2156
29.20
)
;
--focus
:
#DA241A
;
--foreground
:
oklch
(
21.03%
0.0000
29.20
);
--foreground
:
oklch
(
21.03%
0.0000
29.20
);
--muted
:
oklch
(
55.17%
0.0000
29.20
);
--muted
:
oklch
(
55.17%
0.0000
29.20
);
--overlay
:
oklch
(
100.00%
0.0000
29.20
);
--overlay
:
oklch
(
100.00%
0.0000
29.20
);
...
@@ -32,8 +35,8 @@
...
@@ -32,8 +35,8 @@
--segment
:
oklch
(
100.00%
0.0000
29.20
);
--segment
:
oklch
(
100.00%
0.0000
29.20
);
--segment-foreground
:
oklch
(
21.03%
0.0000
29.20
);
--segment-foreground
:
oklch
(
21.03%
0.0000
29.20
);
--separator
:
oklch
(
92.00%
0.0000
29.20
);
--separator
:
oklch
(
92.00%
0.0000
29.20
);
--success
:
oklch
(
73.29%
0.1935
123.85
)
;
--success
:
#61758F
;
--success-foreground
:
oklch
(
21.03%
0.0059
123.85
)
;
--success-foreground
:
#ffffff
;
--surface
:
oklch
(
100.00%
0.0000
29.20
);
--surface
:
oklch
(
100.00%
0.0000
29.20
);
--surface-foreground
:
oklch
(
21.03%
0.0000
29.20
);
--surface-foreground
:
oklch
(
21.03%
0.0000
29.20
);
--surface-secondary
:
oklch
(
95.24%
0.0000
29.20
);
--surface-secondary
:
oklch
(
95.24%
0.0000
29.20
);
...
@@ -70,24 +73,24 @@
...
@@ -70,24 +73,24 @@
* Ant Design remains the icon source. Resolve these CSS variables to
* Ant Design remains the icon source. Resolve these CSS variables to
* concrete colors before assigning them to an ECharts option object.
* concrete colors before assigning them to an ECharts option object.
*/
*/
/*
First pass: red -> pink -> orange -> yellow -> blue -> purple -> cyan -> neutral. */
/*
Coordinated low-conflict chart palette: brand, warm neutrals, mauve
--xinyuan-chart-1
:
#991b1b
;
neutrals and restrained blue-greys. */
--xinyuan-chart-
2
:
#db2777
;
--xinyuan-chart-
1
:
#DA241A
;
--xinyuan-chart-
3
:
#ea580c
;
--xinyuan-chart-
2
:
#B83A32
;
--xinyuan-chart-
4
:
#eab308
;
--xinyuan-chart-
3
:
#C95A52
;
--xinyuan-chart-
5
:
#1d4ed8
;
--xinyuan-chart-
4
:
#D47A70
;
--xinyuan-chart-
6
:
#7e22ce
;
--xinyuan-chart-
5
:
#A65A45
;
--xinyuan-chart-
7
:
#0891b2
;
--xinyuan-chart-
6
:
#B87958
;
--xinyuan-chart-
8
:
#475569
;
--xinyuan-chart-
7
:
#C99772
;
/* Second pass: stronger/lighter companions for charts with more series. */
--xinyuan-chart-8
:
#6F6674
;
--xinyuan-chart-9
:
#
dc2626
;
--xinyuan-chart-9
:
#
807783
;
--xinyuan-chart-10
:
#
ec4899
;
--xinyuan-chart-10
:
#
938B96
;
--xinyuan-chart-11
:
#
f97316
;
--xinyuan-chart-11
:
#
4F6380
;
--xinyuan-chart-12
:
#
facc15
;
--xinyuan-chart-12
:
#
61758F
;
--xinyuan-chart-13
:
#
60a5fa
;
--xinyuan-chart-13
:
#
74879A
;
--xinyuan-chart-14
:
#
a855f7
;
--xinyuan-chart-14
:
#
8A6F63
;
--xinyuan-chart-15
:
#
06b6d
4
;
--xinyuan-chart-15
:
#
9A817
4
;
--xinyuan-chart-16
:
#
1e293b
;
--xinyuan-chart-16
:
#
B5A69D
;
--xinyuan-chart-sector-gap
:
var
(
--surface
);
--xinyuan-chart-sector-gap
:
var
(
--surface
);
--xinyuan-chart-sector-radius
:
10px
;
--xinyuan-chart-sector-radius
:
10px
;
--xinyuan-chart-grid
:
#e8e8e8
;
--xinyuan-chart-grid
:
#e8e8e8
;
...
@@ -105,8 +108,11 @@
...
@@ -105,8 +108,11 @@
[
data-theme
=
"dark"
]
{
[
data-theme
=
"dark"
]
{
color-scheme
:
dark
;
color-scheme
:
dark
;
/* Theme Colors (Dark Mode) */
/* Theme Colors (Dark Mode) */
--accent
:
oklch
(
57.14%
0.2156
29.20
);
/* Keep the primary brand stable across themes. */
--accent
:
#DA241A
;
--accent-foreground
:
oklch
(
99.11%
0
0
);
--accent-foreground
:
oklch
(
99.11%
0
0
);
--accent-hover
:
#C91F17
;
--accent-pressed
:
#B51B14
;
--background
:
oklch
(
12.00%
0.0000
29.20
);
--background
:
oklch
(
12.00%
0.0000
29.20
);
--border
:
oklch
(
28.00%
0.0000
29.20
);
--border
:
oklch
(
28.00%
0.0000
29.20
);
--danger
:
oklch
(
62%
0.16
27.03
);
--danger
:
oklch
(
62%
0.16
27.03
);
...
@@ -117,7 +123,7 @@
...
@@ -117,7 +123,7 @@
--field-border
:
transparent
;
--field-border
:
transparent
;
--field-foreground
:
oklch
(
99.11%
0.0000
29.20
);
--field-foreground
:
oklch
(
99.11%
0.0000
29.20
);
--field-placeholder
:
oklch
(
70.50%
0.0000
29.20
);
--field-placeholder
:
oklch
(
70.50%
0.0000
29.20
);
--focus
:
oklch
(
57.14%
0.2156
29.20
)
;
--focus
:
#DA241A
;
--foreground
:
oklch
(
99.11%
0.0000
29.20
);
--foreground
:
oklch
(
99.11%
0.0000
29.20
);
--muted
:
oklch
(
70.50%
0.0000
29.20
);
--muted
:
oklch
(
70.50%
0.0000
29.20
);
--overlay
:
oklch
(
21.03%
0.0000
29.20
);
--overlay
:
oklch
(
21.03%
0.0000
29.20
);
...
@@ -126,8 +132,8 @@
...
@@ -126,8 +132,8 @@
--segment
:
oklch
(
39.64%
0.0000
29.20
);
--segment
:
oklch
(
39.64%
0.0000
29.20
);
--segment-foreground
:
oklch
(
99.11%
0.0000
29.20
);
--segment-foreground
:
oklch
(
99.11%
0.0000
29.20
);
--separator
:
oklch
(
25.00%
0.0000
29.20
);
--separator
:
oklch
(
25.00%
0.0000
29.20
);
--success
:
oklch
(
73.29%
0.1935
123.85
)
;
--success
:
#74879A
;
--success-foreground
:
oklch
(
21.03%
0.0059
123.85
)
;
--success-foreground
:
#ffffff
;
--surface
:
oklch
(
21.03%
0.0000
29.20
);
--surface
:
oklch
(
21.03%
0.0000
29.20
);
--surface-foreground
:
oklch
(
99.11%
0.0000
29.20
);
--surface-foreground
:
oklch
(
99.11%
0.0000
29.20
);
--surface-secondary
:
oklch
(
25.70%
0.0000
29.20
);
--surface-secondary
:
oklch
(
25.70%
0.0000
29.20
);
...
...
src/design-system/tokens.css
View file @
90949774
...
@@ -4,10 +4,26 @@
...
@@ -4,10 +4,26 @@
[
data-theme
=
'light'
],
[
data-theme
=
'light'
],
[
data-theme
=
'default'
]
{
[
data-theme
=
'default'
]
{
/* Xinyuan aliases and extension tokens. HeroUI core tokens are owned by theme.css. */
/* Xinyuan aliases and extension tokens. HeroUI core tokens are owned by theme.css. */
--rc-brand-primary
:
var
(
--accent
)
;
--rc-brand-primary
:
#DA241A
;
--rc-brand-light
:
color-mix
(
in
oklab
,
var
(
--accent
)
84%
,
white
);
--rc-brand-light
:
color-mix
(
in
oklab
,
var
(
--accent
)
84%
,
white
);
--rc-brand-dark
:
color-mix
(
in
oklab
,
var
(
--accent
)
82%
,
black
);
--rc-brand-dark
:
color-mix
(
in
oklab
,
var
(
--accent
)
82%
,
black
);
/* Compatibility aliases for integrations that still read numbered primary
tokens. HeroUI v3 components consume --accent and --accent-hover. */
--primary
:
#DA241A
;
--primary-foreground
:
#ffffff
;
--primary-50
:
#FFF1F0
;
--primary-100
:
#FFE0DD
;
--primary-200
:
#FFC2BD
;
--primary-300
:
#FFA39C
;
--primary-400
:
#F26D63
;
--primary-500
:
#DA241A
;
--primary-600
:
#C91F17
;
--primary-700
:
#B51B14
;
--primary-800
:
#8F1711
;
--primary-900
:
#6F120E
;
--primary-950
:
#4B0C09
;
--rc-bg-canvas
:
var
(
--background
);
--rc-bg-canvas
:
var
(
--background
);
--rc-bg-surface
:
var
(
--surface
);
--rc-bg-surface
:
var
(
--surface
);
--rc-border-default
:
var
(
--border
);
--rc-border-default
:
var
(
--border
);
...
@@ -92,14 +108,14 @@
...
@@ -92,14 +108,14 @@
0
4px
12px
rgb
(
15
23
42
/
2%
);
0
4px
12px
rgb
(
15
23
42
/
2%
);
/* KPI icon surfaces. Card bodies remain neutral; only the icon well carries tone. */
/* KPI icon surfaces. Card bodies remain neutral; only the icon well carries tone. */
--rc-metric-tone-info
:
oklch
(
55%
0.14
255
);
--rc-metric-tone-info
:
var
(
--rc-chart-11
);
--rc-metric-tone-success
:
oklch
(
54%
0.13
145
);
--rc-metric-tone-success
:
var
(
--rc-chart-12
);
--rc-metric-tone-teal
:
oklch
(
55%
0.1
205
);
--rc-metric-tone-teal
:
var
(
--rc-chart-14
);
--rc-metric-tone-danger
:
oklch
(
52%
0.17
25
);
--rc-metric-tone-danger
:
var
(
--rc-chart-1
);
--rc-metric-tone-warning
:
oklch
(
62%
0.12
75
);
--rc-metric-tone-warning
:
var
(
--rc-chart-6
);
--rc-metric-tone-violet
:
oklch
(
56%
0.12
300
);
--rc-metric-tone-violet
:
var
(
--rc-chart-9
);
--rc-metric-tone-indigo
:
oklch
(
53%
0.13
275
);
--rc-metric-tone-indigo
:
var
(
--rc-chart-13
);
--rc-metric-tone-coral
:
oklch
(
60%
0.12
48
);
--rc-metric-tone-coral
:
var
(
--rc-chart-3
);
--rc-metric-tone-neutral
:
var
(
--muted
);
--rc-metric-tone-neutral
:
var
(
--muted
);
--rc-metric-tone-info-soft
:
color-mix
(
--rc-metric-tone-info-soft
:
color-mix
(
in
oklab
,
in
oklab
,
...
@@ -167,8 +183,8 @@
...
@@ -167,8 +183,8 @@
--rc-chart-primary
:
var
(
--rc-chart-1
);
--rc-chart-primary
:
var
(
--rc-chart-1
);
--rc-chart-risk
:
var
(
--rc-chart-1
);
--rc-chart-risk
:
var
(
--rc-chart-1
);
--rc-chart-warning
:
var
(
--rc-chart-3
);
--rc-chart-warning
:
var
(
--rc-chart-3
);
--rc-chart-positive
:
var
(
--rc-chart-
7
);
--rc-chart-positive
:
var
(
--rc-chart-
12
);
--rc-chart-comparison
:
var
(
--rc-chart-
5
);
--rc-chart-comparison
:
var
(
--rc-chart-
11
);
--rc-chart-neutral
:
var
(
--rc-chart-8
);
--rc-chart-neutral
:
var
(
--rc-chart-8
);
--rc-chart-legend-font-size
:
var
(
--xinyuan-chart-legend-font-size
);
--rc-chart-legend-font-size
:
var
(
--xinyuan-chart-legend-font-size
);
--rc-chart-legend-line-height
:
var
(
--xinyuan-chart-legend-line-height
);
--rc-chart-legend-line-height
:
var
(
--xinyuan-chart-legend-line-height
);
...
...
src/design-system/useXinyuanChartTheme.js
View file @
90949774
import
{
useMemo
}
from
'react'
;
import
{
useMemo
}
from
'react'
;
import
{
getXinyuanChartColors
}
from
'./chartTokens'
;
function
readToken
(
name
,
fallback
)
{
function
readToken
(
name
,
fallback
)
{
if
(
typeof
window
===
'undefined'
)
return
fallback
;
if
(
typeof
window
===
'undefined'
)
return
fallback
;
...
@@ -12,7 +13,7 @@ export default function useXinyuanChartTheme(theme = 'light') {
...
@@ -12,7 +13,7 @@ export default function useXinyuanChartTheme(theme = 'light') {
const
muted
=
readToken
(
'--rc-text-muted'
,
theme
===
'dark'
?
'#a1a1aa'
:
'#718096'
);
const
muted
=
readToken
(
'--rc-text-muted'
,
theme
===
'dark'
?
'#a1a1aa'
:
'#718096'
);
const
border
=
readToken
(
'--rc-border-default'
,
theme
===
'dark'
?
'#303036'
:
'#e3e8ef'
);
const
border
=
readToken
(
'--rc-border-default'
,
theme
===
'dark'
?
'#303036'
:
'#e3e8ef'
);
return
{
return
{
colors
:
[
'#9e1b1b'
,
'#16845b'
,
'#b46a00'
,
'#0f766e'
,
'#718096'
]
,
colors
:
getXinyuanChartColors
()
,
axisLine
:
{
lineStyle
:
{
color
:
border
}
},
axisLine
:
{
lineStyle
:
{
color
:
border
}
},
axisLabel
:
{
color
:
muted
,
fontSize
:
12
},
axisLabel
:
{
color
:
muted
,
fontSize
:
12
},
splitLine
:
{
lineStyle
:
{
color
:
border
,
opacity
:
0.7
}
},
splitLine
:
{
lineStyle
:
{
color
:
border
,
opacity
:
0.7
}
},
...
...
src/pages/integrity_practice_management/SubjectWorkbench.jsx
View file @
90949774
...
@@ -325,6 +325,9 @@ export default function SubjectWorkbench() {
...
@@ -325,6 +325,9 @@ export default function SubjectWorkbench() {
setFilters
({});
setFilters
({});
setPage
(
0
);
setPage
(
0
);
}
}
}
}
onQuery=
{
()
=>
{
setRefreshKey
((
value
)
=>
value
+
1
);
}
}
title=
{
subjectConfig
.
title
||
subject
?.
title
||
subjectName
}
title=
{
subjectConfig
.
title
||
subject
?.
title
||
subjectName
}
listTitle=
{
subjectConfig
.
listTitle
}
listTitle=
{
subjectConfig
.
listTitle
}
description=
{
description=
{
...
...
src/pages/integrity_practice_management/integrityPracticeWorkbenchService.js
View file @
90949774
...
@@ -37,7 +37,7 @@ import { saveAs } from 'file-saver';
...
@@ -37,7 +37,7 @@ import { saveAs } from 'file-saver';
import
JSZip
from
'jszip'
;
import
JSZip
from
'jszip'
;
import
*
as
XLSX
from
'xlsx'
;
import
*
as
XLSX
from
'xlsx'
;
export
const
DEFAULT_PAGE_SIZE
=
1
0
;
export
const
DEFAULT_PAGE_SIZE
=
2
0
;
function
normalizeFilterFieldPath
(
field
)
{
function
normalizeFilterFieldPath
(
field
)
{
const
value
=
typeof
field
===
'string'
?
field
.
trim
()
:
''
;
const
value
=
typeof
field
===
'string'
?
field
.
trim
()
:
''
;
...
...
src/pages/problem_rectification/dashboard/index.jsx
View file @
90949774
...
@@ -20,8 +20,9 @@ import clsx from 'clsx';
...
@@ -20,8 +20,9 @@ import clsx from 'clsx';
import
dayjs
from
'dayjs'
;
import
dayjs
from
'dayjs'
;
import
{
useEffect
,
useMemo
,
useState
}
from
'react'
;
import
{
useEffect
,
useMemo
,
useState
}
from
'react'
;
import
{
loadProblemRectificationDashboardData
}
from
'../problemRectificationDashboardService'
;
import
{
loadProblemRectificationDashboardData
}
from
'../problemRectificationDashboardService'
;
import
{
XINYUAN_CHART_COLORS
}
from
'@/design-system/chartTokens'
;
const
CHART_COLOR_SET
=
[
'#e11d48'
,
'#fb7185'
,
'#f97316'
,
'#f59e0b'
,
'#22c55e'
,
'#0ea5e9'
,
'#8b5cf6'
]
;
const
CHART_COLOR_SET
=
XINYUAN_CHART_COLORS
;
const
CATEGORY_LEVEL_TABS
=
[
const
CATEGORY_LEVEL_TABS
=
[
{
key
:
'level1'
,
label
:
'一级分类'
},
{
key
:
'level1'
,
label
:
'一级分类'
},
{
key
:
'level2'
,
label
:
'二级分类'
},
{
key
:
'level2'
,
label
:
'二级分类'
},
...
@@ -34,24 +35,24 @@ const FOCUS_ISSUE_TYPES = [
...
@@ -34,24 +35,24 @@ const FOCUS_ISSUE_TYPES = [
label
:
'经济损失问题'
,
label
:
'经济损失问题'
,
shortLabel
:
'经济损失'
,
shortLabel
:
'经济损失'
,
description
:
'造成经济损失且严重程度较高的问题。'
,
description
:
'造成经济损失且严重程度较高的问题。'
,
color
:
'#e11d48'
,
color
:
CHART_COLOR_SET
[
0
]
,
badgeClass
:
'bg-
rose-50 text-rose-700
'
,
badgeClass
:
'bg-
[color-mix(in_oklab,var(--rc-chart-1)_12%,var(--surface))] text-[var(--rc-chart-1)]
'
,
},
},
{
{
key
:
'externalImpact'
,
key
:
'externalImpact'
,
label
:
'外部影响问题'
,
label
:
'外部影响问题'
,
shortLabel
:
'外部影响'
,
shortLabel
:
'外部影响'
,
description
:
'涉及处罚机构或外部影响的问题。'
,
description
:
'涉及处罚机构或外部影响的问题。'
,
color
:
'#f59e0b'
,
color
:
CHART_COLOR_SET
[
5
]
,
badgeClass
:
'bg-
amber-50 text-amber-700
'
,
badgeClass
:
'bg-
[color-mix(in_oklab,var(--rc-chart-6)_14%,var(--surface))] text-[var(--rc-chart-6)]
'
,
},
},
{
{
key
:
'accountability'
,
key
:
'accountability'
,
label
:
'员工问责问题'
,
label
:
'员工问责问题'
,
shortLabel
:
'员工问责'
,
shortLabel
:
'员工问责'
,
description
:
'已触发员工问责后果的问题。'
,
description
:
'已触发员工问责后果的问题。'
,
color
:
'#0ea5e9'
,
color
:
CHART_COLOR_SET
[
10
]
,
badgeClass
:
'bg-
sky-50 text-sky-700
'
,
badgeClass
:
'bg-
[color-mix(in_oklab,var(--rc-chart-11)_12%,var(--surface))] text-[var(--rc-chart-11)]
'
,
},
},
];
];
...
@@ -72,25 +73,13 @@ function formatCount(value) {
...
@@ -72,25 +73,13 @@ function formatCount(value) {
}
}
function
toneCardClass
(
tone
)
{
function
toneCardClass
(
tone
)
{
if
(
tone
===
'rose'
)
{
return
'rc-card-surface rc-dashboard-card'
;
return
'border-rose-200 bg-[linear-gradient(135deg,rgba(255,241,242,0.95),rgba(255,255,255,0.9))]'
;
}
if
(
tone
===
'amber'
)
{
return
'border-amber-200 bg-[linear-gradient(135deg,rgba(255,251,235,0.95),rgba(255,255,255,0.92))]'
;
}
if
(
tone
===
'emerald'
)
{
return
'border-emerald-200 bg-[linear-gradient(135deg,rgba(236,253,245,0.95),rgba(255,255,255,0.92))]'
;
}
if
(
tone
===
'sky'
)
{
return
'border-sky-200 bg-[linear-gradient(135deg,rgba(240,249,255,0.95),rgba(255,255,255,0.92))]'
;
}
return
'border-zinc-200 bg-[linear-gradient(135deg,rgba(250,250,250,0.95),rgba(255,255,255,0.92))]'
;
}
}
function
SectionHeading
({
eyebrow
,
title
,
description
})
{
function
SectionHeading
({
eyebrow
,
title
,
description
})
{
return
(
return
(
<
div
className=
"space-y-2"
>
<
div
className=
"space-y-2"
>
<
div
className=
"text-xs font-semibold uppercase tracking-[0.24em] text-
rose-500
"
>
<
div
className=
"text-xs font-semibold uppercase tracking-[0.24em] text-
[var(--rc-brand-primary)]
"
>
{
eyebrow
}
{
eyebrow
}
</
div
>
</
div
>
<
div
className=
"text-2xl font-semibold tracking-tight text-slate-950"
>
{
title
}
</
div
>
<
div
className=
"text-2xl font-semibold tracking-tight text-slate-950"
>
{
title
}
</
div
>
...
@@ -105,7 +94,7 @@ function StatCard({ label, value, hint, tone = 'default' }) {
...
@@ -105,7 +94,7 @@ function StatCard({ label, value, hint, tone = 'default' }) {
return
(
return
(
<
div
<
div
className=
{
clsx
(
className=
{
clsx
(
'
rounded-[28px] border p-5 shadow-[0_16px_40px_rgba(15,23,42,0.06)]
'
,
'
p-5
'
,
toneCardClass
(
tone
),
toneCardClass
(
tone
),
)
}
)
}
>
>
...
@@ -233,7 +222,7 @@ function buildDonutOption(data, colors) {
...
@@ -233,7 +222,7 @@ function buildDonutOption(data, colors) {
function
buildCategoryBarOption
(
data
=
[])
{
function
buildCategoryBarOption
(
data
=
[])
{
return
{
return
{
color
:
[
'#e11d48'
],
color
:
[
CHART_COLOR_SET
[
0
]
],
tooltip
:
{
tooltip
:
{
trigger
:
'axis'
,
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
},
axisPointer
:
{
type
:
'shadow'
},
...
@@ -478,10 +467,10 @@ function buildBubbleMatrixOption(data = []) {
...
@@ -478,10 +467,10 @@ function buildBubbleMatrixOption(data = []) {
itemStyle: {
itemStyle: {
color:
color:
item.completionRate >= 75
item.completionRate >= 75
?
'#22c55e'
?
CHART_COLOR_SET[10]
: item.completionRate >= 45
: item.completionRate >= 45
?
'#f59e0b'
?
CHART_COLOR_SET[5]
:
'#e11d48'
,
:
CHART_COLOR_SET[0]
,
opacity: 0.85,
opacity: 0.85,
},
},
label: {
label: {
...
@@ -582,7 +571,7 @@ function buildBubbleMatrixOption(data = []) {
...
@@ -582,7 +571,7 @@ function buildBubbleMatrixOption(data = []) {
function buildQualityRatingOption(data)
{
function buildQualityRatingOption(data)
{
return
{
return
{
color
:
[
'#22c55e'
,
'#f59e0b'
,
'#e11d48'
],
color
:
[
CHART_COLOR_SET
[
10
],
CHART_COLOR_SET
[
5
],
CHART_COLOR_SET
[
0
]
],
tooltip
:
{
tooltip
:
{
trigger
:
'item'
,
trigger
:
'item'
,
backgroundColor
:
'rgba(15,23,42,0.9)'
,
backgroundColor
:
'rgba(15,23,42,0.9)'
,
...
@@ -707,7 +696,7 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
...
@@ -707,7 +696,7 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
[
summary
.
sourceComparison
],
[
summary
.
sourceComparison
],
);
);
const
overdueRankingOption
=
useMemo
(
const
overdueRankingOption
=
useMemo
(
()
=>
buildHorizontalBarOption
(
summary
.
overdueRanking
,
'#e11d48'
),
()
=>
buildHorizontalBarOption
(
summary
.
overdueRanking
,
CHART_COLOR_SET
[
0
]
),
[
summary
.
overdueRanking
],
[
summary
.
overdueRanking
],
);
);
const
departmentMatrixOption
=
useMemo
(
const
departmentMatrixOption
=
useMemo
(
...
@@ -756,7 +745,7 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
...
@@ -756,7 +745,7 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
return
(
return
(
<
div
className=
"space-y-8"
>
<
div
className=
"space-y-8"
>
<
section
className=
"relative overflow-hidden rounded-[34px] border border-white/
80 bg-[linear-gradient(135deg,rgba(124,24,24,0.96),rgba(190,24,93,0.92)_54%,rgba(244,63,94,0.9))] px-6 py-7 text-white shadow-[0_28px_80px_rgba(159,18,57
,0.24)]"
>
<
section
className=
"relative overflow-hidden rounded-[34px] border border-white/
20 bg-[var(--rc-brand-primary)] px-6 py-7 text-white shadow-[0_28px_80px_rgba(218,36,26
,0.24)]"
>
<
div
className=
"absolute inset-y-0 right-0 w-[36%] bg-[radial-gradient(circle_at_top_right,rgba(255,255,255,0.28),transparent_45%)]"
/>
<
div
className=
"absolute inset-y-0 right-0 w-[36%] bg-[radial-gradient(circle_at_top_right,rgba(255,255,255,0.28),transparent_45%)]"
/>
<
div
className=
"absolute -bottom-16 left-1/3 h-40 w-40 rounded-full bg-white/10 blur-3xl"
/>
<
div
className=
"absolute -bottom-16 left-1/3 h-40 w-40 rounded-full bg-white/10 blur-3xl"
/>
<
div
className=
"relative flex flex-wrap items-end justify-between gap-6"
>
<
div
className=
"relative flex flex-wrap items-end justify-between gap-6"
>
...
@@ -791,8 +780,8 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
...
@@ -791,8 +780,8 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
className=
{
clsx
(
className=
{
clsx
(
'rounded-[20px] px-4 py-3 text-sm font-medium transition-all duration-200'
,
'rounded-[20px] px-4 py-3 text-sm font-medium transition-all duration-200'
,
activeGroupKey
===
group
.
key
activeGroupKey
===
group
.
key
?
'bg-[
linear-gradient(135deg,#7f1d1d,#be123c
)] text-white shadow-lg'
?
'bg-[
var(--rc-brand-primary
)] text-white shadow-lg'
:
'text-slate-600 hover:bg-
rose-50 hover:text-rose-700
'
,
:
'text-slate-600 hover:bg-
[color-mix(in_oklab,var(--rc-brand-primary)_8%,var(--surface))] hover:text-[var(--rc-brand-primary)]
'
,
)
}
)
}
>
>
{
group
.
label
}
{
group
.
label
}
...
@@ -864,7 +853,7 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
...
@@ -864,7 +853,7 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
label=
"已完成整改数"
label=
"已完成整改数"
value=
{
formatCount
(
summary
.
fixedCount
)
}
value=
{
formatCount
(
summary
.
fixedCount
)
}
hint=
"整改进度为已整改或已优化"
hint=
"整改进度为已整改或已优化"
tone=
"
emerald
"
tone=
"
neutral
"
/>
/>
<
StatCard
<
StatCard
label=
"整改完成率"
label=
"整改完成率"
...
@@ -932,8 +921,8 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
...
@@ -932,8 +921,8 @@ export function ProblemRectificationDashboardPage({ dashboardMode = 'overview' }
className=
{
clsx
(
className=
{
clsx
(
'min-h-11 rounded-full border px-4 text-sm font-medium transition'
,
'min-h-11 rounded-full border px-4 text-sm font-medium transition'
,
isActive
isActive
?
'border-
rose-500 bg-rose-500
text-white shadow-sm'
?
'border-
[var(--rc-brand-primary)] bg-[var(--rc-brand-primary)]
text-white shadow-sm'
:
'border-zinc-200 bg-white text-slate-600 hover:border-
rose-200 hover:bg-rose-50 hover:text-rose-700
'
,
:
'border-zinc-200 bg-white text-slate-600 hover:border-
[var(--rc-brand-primary)] hover:bg-[color-mix(in_oklab,var(--rc-brand-primary)_8%,var(--surface))] hover:text-[var(--rc-brand-primary)]
'
,
)
}
)
}
onClick=
{
()
=>
setActiveCategoryLevel
(
tab
.
key
)
}
onClick=
{
()
=>
setActiveCategoryLevel
(
tab
.
key
)
}
>
>
...
...
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