Commit aada7aec authored by Andy-bubu's avatar Andy-bubu

feat: refine chart palette and filter layout

parent dedde183
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
- [x] Login:审计项目管理几何、字段节奏、验证码和 filled/autofill - [x] Login:审计项目管理几何、字段节奏、验证码和 filled/autofill
- [x] Shell:Sidebar/Navbar/退出/应用切换/offcanvas(审计项目管理结构) - [x] Shell:Sidebar/Navbar/退出/应用切换/offcanvas(审计项目管理结构)
- [x] 应用切换:同步审计项目管理 Modal 几何、动态分组/计数、其他/全部回退、两列 Card 与 identity well(代码结构) - [x] 应用切换:同步审计项目管理 Modal 几何、动态分组/计数、其他/全部回退、两列 Card 与 identity well(代码结构)
- [x] 驾驶舱:Pro KPI、PieChart、BarChart、ComposedChart、ChartTooltip;环形扇区间隙/10px 扇区圆角、柱图 8px 末端圆角与 24px 分析模块圆角(代码结构) - [x] 驾驶舱:Pro KPI、统一 `XinyuanEChart`/ECharts;环形扇区间隙/10px 扇区圆角/外部引导线、柱图 8px 末端圆角与 24px 分析模块圆角(代码结构)
- [x] 案例管理:Tabs、筛选工具栏、DataGrid、Pagination、ActionBar、EmptyState(代码结构) - [x] 案例管理:Tabs、筛选工具栏、DataGrid、Pagination、ActionBar、EmptyState(代码结构)
- [x] 弹窗:新建、查看/编辑、批量修改、导入、删除确认(代码结构) - [x] 弹窗:新建、查看/编辑、批量修改、导入、删除确认(代码结构)
- [x] 清除 Catalyst/Headless/ECharts/原生可见控件与页面私有视觉 CSS - [x] 清除 Catalyst/Headless/旧图表调用/原生可见控件与页面私有视觉 CSS
## 四项功能 ## 四项功能
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
## 依赖与样式 ## 依赖与样式
- 基础控件直接从 `@heroui/react` 导入。 - 基础控件直接从 `@heroui/react` 导入。
- Sidebar、Navbar、DataGrid、ActionBar、EmptyState、DropZone、KPI 与图表从 `@heroui-pro/react` 对应子路径直接导入。 - Sidebar、Navbar、DataGrid、ActionBar、EmptyState、DropZone 与 KPI 从 `@heroui-pro/react` 对应子路径直接导入;业务图表统一通过共享 `XinyuanEChart` 使用 ECharts。
- 样式顺序固定为 Tailwind、HeroUI、HeroUI Pro、`theme.css`、`tokens.css`、批准的共享布局层。 - 样式顺序固定为 Tailwind、HeroUI、HeroUI Pro、`theme.css`、`tokens.css`、批准的共享布局层。
- 本轮 `theme.css` 与 `tokens.css` 必须与审计项目管理当前版本逐字节一致;页面不得覆盖 HeroUI 外观、slot、BEM 类或交互状态。 - 本轮 `theme.css` 与 `tokens.css` 必须与审计项目管理当前版本逐字节一致;页面不得覆盖 HeroUI 外观、slot、BEM 类或交互状态。
- 页面 `className` 只承担 flex、grid、宽度、间距、对齐和响应式布局。 - 页面 `className` 只承担 flex、grid、宽度、间距、对齐和响应式布局。
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
- 列表使用 HeroUI Pro DataGrid 原生选择、排序、固定列、ActionBar、EmptyState 与 Pagination;宽表由共享 `.data-table-scroll` 承担横纵向滚动,首业务列及操作列固定,分页保留真实 20/50/100 条数选择。 - 列表使用 HeroUI Pro DataGrid 原生选择、排序、固定列、ActionBar、EmptyState 与 Pagination;宽表由共享 `.data-table-scroll` 承担横纵向滚动,首业务列及操作列固定,分页保留真实 20/50/100 条数选择。
- 页容量选择使用现有 HeroUI Autocomplete 的受控 value 合同;切换容量只重置列表页码并复用既有查询回调,不改变筛选、排序或服务请求协议。 - 页容量选择使用现有 HeroUI Autocomplete 的受控 value 合同;切换容量只重置列表页码并复用既有查询回调,不改变筛选、排序或服务请求协议。
- 详情和内容型表单使用鑫元 4xl(1088px)Modal:HeroUI `Modal.Container size="lg"` 保留官方交互与响应式结构,`Modal.Dialog` 通过共享布局类限制为 `bg-background p-7 sm:max-w-[68rem]`,使详情背景与页面画布一致;查看态不添加灰色嵌套 Surface,编辑态直接放置 `secondary` 控件。 - 详情和内容型表单使用鑫元 4xl(1088px)Modal:HeroUI `Modal.Container size="lg"` 保留官方交互与响应式结构,`Modal.Dialog` 通过共享布局类限制为 `bg-background p-7 sm:max-w-[68rem]`,使详情背景与页面画布一致;查看态不添加灰色嵌套 Surface,编辑态直接放置 `secondary` 控件。
- 指标必须使用 HeroUI Pro KPI compound API;图表必须使用 Pro PieChart、BarChart、ComposedChart 与 ChartTooltipContent。 - 指标必须使用 HeroUI Pro KPI compound API;所有业务图表统一使用共享 `XinyuanEChart` ECharts 渲染器,图表主题、Tooltip、坐标轴和颜色由鑫元 Token 统一注入。
- 图表业务序列只使用 `--rc-chart-*` Token,不使用 UI 状态色或页面硬编码颜色。 - 图表业务序列只使用 `--rc-chart-*` Token,不使用 UI 状态色或页面硬编码颜色。
- 环形图通过共享 `--xinyuan-chart-sector-gap`、`--xinyuan-chart-sector-radius` 呈现扇区间隙与 10px 扇区圆角;柱图通过共享图表几何统一使用 8px 末端圆角。分析卡片沿用 `.rc-dashboard-card` 的 24px 外圆角。 - 环形图通过共享 `--xinyuan-chart-sector-gap`、`--xinyuan-chart-sector-radius` 呈现扇区间隙与 10px 扇区圆角;柱图通过共享图表几何统一使用 8px 末端圆角。分析卡片沿用 `.rc-dashboard-card` 的 24px 外圆角。
...@@ -36,6 +36,6 @@ ...@@ -36,6 +36,6 @@
## 禁止项 ## 禁止项
- Catalyst、Headless UI、旧 UI 包装层、可见原生 select/date/file 控件。 - Catalyst、Headless UI、旧 UI 包装层、可见原生 select/date/file 控件。
- ECharts、自制 Tooltip、自制表格/分页/弹窗/KPI 或 HeroUI 仿制组件。 - 自制 Tooltip、自制表格/分页/弹窗/KPI 或 HeroUI 仿制组件;业务图表不得回退到 HeroUI Pro Recharts 封装。
- 页面私有背景、颜色、边框、圆角、阴影、Hover、Focus、Selected、Disabled 样式。 - 页面私有背景、颜色、边框、圆角、阴影、Hover、Focus、Selected、Disabled 样式。
- `file:`、工作站绝对路径、相邻项目 `node_modules` 或符号链接依赖。 - `file:`、工作站绝对路径、相邻项目 `node_modules` 或符号链接依赖。
...@@ -24,10 +24,10 @@ ...@@ -24,10 +24,10 @@
| Login | HeroUI;结构、尺寸、字段节奏与审计项目管理一致;可访问性告警已消除 | 固定浅色 Shell;本次复核受服务端验证码阻塞 | | Login | HeroUI;结构、尺寸、字段节奏与审计项目管理一致;可访问性告警已消除 | 固定浅色 Shell;本次复核受服务端验证码阻塞 |
| Shell | HeroUI Pro Sidebar/Navbar,offcanvas、主题、用户退出与应用切换保留既有业务回调 | 代码与共享基准一致;登录后浏览器状态待真实凭证 | | Shell | HeroUI Pro Sidebar/Navbar,offcanvas、主题、用户退出与应用切换保留既有业务回调 | 代码与共享基准一致;登录后浏览器状态待真实凭证 |
| 应用切换 | HeroUI Modal compound API;46rem/42rem/28px 几何;读取 `/info -> site.group` 动态分组、真实计数与未分组回退;两列 Card、Surface + Avatar identity、唯一当前态 | 与审计项目管理的两列/移动端单列结构一致 | | 应用切换 | HeroUI Modal compound API;46rem/42rem/28px 几何;读取 `/info -> site.group` 动态分组、真实计数与未分组回退;两列 Card、Surface + Avatar identity、唯一当前态 | 与审计项目管理的两列/移动端单列结构一致 |
| 驾驶舱 | HeroUI Pro KPI、PieChart、BarChart、ComposedChart、ChartTooltipContent | 环形图使用共享扇区间隙与 10px 圆角;两类柱图使用 8px 末端圆角;外层分析 Card 为 24px。真实图表 Tooltip 待登录验收 | | 驾驶舱 | HeroUI Pro KPI;统一 `XinyuanEChart`/ECharts 渲染器 | 环形图使用共享扇区间隙、10px 扇区圆角和外部引导线;两类柱图使用 8px 末端圆角;外层分析 Card 为 24px。真实图表 Tooltip 待登录验收 |
| 案例管理 | HeroUI Surface/Tabs/TextField/Autocomplete、Pro DataGrid/ActionBar/EmptyState | 默认 20、20/50/100 分页口径已保护;交互待登录验收 | | 案例管理 | HeroUI Surface/Tabs/TextField/Autocomplete、Pro DataGrid/ActionBar/EmptyState | 默认 20、20/50/100 分页口径已保护;交互待登录验收 |
| 弹窗 | HeroUI Modal/Alert/DropZone,Container 使用官方 `lg`、Dialog 映射鑫元 4xl/1088px,详情 Dialog 使用 `bg-background` 并取消查看态灰色嵌套 Surface | 真实打开态已确认 Dialog 与页面画布同色 | | 弹窗 | HeroUI Modal/Alert/DropZone,Container 使用官方 `lg`、Dialog 映射鑫元 4xl/1088px,详情 Dialog 使用 `bg-background` 并取消查看态灰色嵌套 Surface | 真实打开态已确认 Dialog 与页面画布同色 |
| 旧组件 | Catalyst、Headless、旧 Select/Date/Table 兼容层已移除 | 活动源码无旧 UI 导入;图表沿用审计项目管理的 HeroUI Pro + Recharts primitive 组合 | | 旧组件 | Catalyst、Headless、旧 Select/Date/Table 兼容层已移除 | 活动源码无旧 UI 导入;所有业务图表统一使用 `XinyuanEChart` + ECharts,未保留 HeroUI Pro Recharts 图表调用 |
| 样式 | `theme.css`、`tokens.css` 已与审计项目管理逐字节一致;`shell.css` 保留当前项目所需的 Sidebar 状态、固定列和 Autocomplete 交互扩展 | `portable.css` 与页面私有视觉 CSS 已移除 | | 样式 | `theme.css`、`tokens.css` 已与审计项目管理逐字节一致;`shell.css` 保留当前项目所需的 Sidebar 状态、固定列和 Autocomplete 交互扩展 | `portable.css` 与页面私有视觉 CSS 已移除 |
## 四项功能审计 ## 四项功能审计
......
This diff is collapsed.
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"dayjs": "^1.11.20", "dayjs": "^1.11.20",
"echarts": "^6.1.0",
"echarts-for-react": "^3.0.6",
"embla-carousel": ">=8.6.0", "embla-carousel": ">=8.6.0",
"embla-carousel-react": ">=8.6.0", "embla-carousel-react": ">=8.6.0",
"maplibre-gl": ">=6.0.0", "maplibre-gl": ">=6.0.0",
......
import { getXinyuanEChartsTheme } from '@/design-system/chartPalette';
import ReactECharts from 'echarts-for-react';
import { useCallback, useEffect, useMemo, useRef } from 'react';
function mergeAxisTheme(axis, theme) {
if (!axis) return axis;
const applyTheme = (item) => ({
...item,
axisLabel: {
color: theme.axis,
fontFamily: theme.fontFamily,
fontSize: 12,
...item?.axisLabel,
},
axisLine: {
...item?.axisLine,
lineStyle: {
color: theme.grid,
...item?.axisLine?.lineStyle,
},
},
axisTick: {
...item?.axisTick,
lineStyle: {
color: theme.grid,
...item?.axisTick?.lineStyle,
},
},
splitLine: {
...item?.splitLine,
lineStyle: {
color: theme.grid,
...item?.splitLine?.lineStyle,
},
},
});
return Array.isArray(axis) ? axis.map(applyTheme) : applyTheme(axis);
}
export default function XinyuanEChart({
ariaLabel,
className = '',
height = 320,
onEvents,
option,
}) {
const chartRef = useRef(null);
const hideTooltip = useCallback(() => {
chartRef.current?.getEchartsInstance?.().dispatchAction({ type: 'hideTip' });
}, []);
useEffect(() => {
window.addEventListener('resize', hideTooltip);
return () => window.removeEventListener('resize', hideTooltip);
}, [hideTooltip]);
const themedOption = useMemo(() => {
const theme = getXinyuanEChartsTheme();
return {
animationDuration: 320,
animationDurationUpdate: 240,
animationEasing: 'cubicOut',
aria: {
enabled: true,
decal: { show: false },
...option?.aria,
},
color: option?.color || theme.palette,
textStyle: {
color: theme.label,
fontFamily: theme.fontFamily,
...option?.textStyle,
},
...option,
legend: option?.legend ? {
icon: 'circle',
itemHeight: 8,
itemWidth: 8,
...option.legend,
textStyle: {
color: theme.label,
fontFamily: theme.fontFamily,
fontSize: 12,
lineHeight: 16,
...option.legend?.textStyle,
},
} : undefined,
tooltip: {
appendToBody: true,
backgroundColor: theme.tooltipBackground,
borderColor: theme.tooltipBorder,
borderWidth: 1,
className: 'rc-echarts-tooltip',
confine: true,
enterable: false,
extraCssText: `border-radius: 12px; box-shadow: ${theme.tooltipShadow};`,
padding: [10, 12],
renderMode: 'html',
...option?.tooltip,
textStyle: {
color: theme.foreground,
fontFamily: theme.fontFamily,
fontSize: 12,
...option?.tooltip?.textStyle,
},
},
xAxis: mergeAxisTheme(option?.xAxis, theme),
yAxis: mergeAxisTheme(option?.yAxis, theme),
};
}, [option]);
return (
<div
aria-label={ariaLabel}
className={`rc-chart-interaction w-full min-w-0 ${className}`.trim()}
role="img"
tabIndex={0}
>
<ReactECharts
lazyUpdate
notMerge
onEvents={{ globalout: hideTooltip, ...onEvents }}
option={themedOption}
opts={{ renderer: 'canvas' }}
ref={chartRef}
style={{ height, width: '100%' }}
/>
</div>
);
}
...@@ -7,6 +7,14 @@ export const XINYUAN_CHART_PALETTE = Object.freeze([ ...@@ -7,6 +7,14 @@ export const XINYUAN_CHART_PALETTE = Object.freeze([
'var(--rc-chart-6)', 'var(--rc-chart-6)',
'var(--rc-chart-7)', 'var(--rc-chart-7)',
'var(--rc-chart-8)', 'var(--rc-chart-8)',
'var(--rc-chart-9)',
'var(--rc-chart-10)',
'var(--rc-chart-11)',
'var(--rc-chart-12)',
'var(--rc-chart-13)',
'var(--rc-chart-14)',
'var(--rc-chart-15)',
'var(--rc-chart-16)',
]); ]);
export const XINYUAN_CHART_SEMANTIC = Object.freeze({ export const XINYUAN_CHART_SEMANTIC = Object.freeze({
...@@ -33,6 +41,53 @@ export function getXinyuanChartGeometry() { ...@@ -33,6 +41,53 @@ export function getXinyuanChartGeometry() {
}; };
} }
function readRootToken(tokenName, fallback = '') {
if (typeof window === 'undefined' || typeof document === 'undefined') {
return fallback;
}
return window.getComputedStyle(document.documentElement)
.getPropertyValue(tokenName)
.trim() || fallback;
}
export function resolveXinyuanChartColor(color, fallback = '') {
const match = String(color || '').trim().match(/^var\((--[^)]+)\)$/);
return match ? readRootToken(match[1], fallback) : String(color || fallback);
}
export function createResolvedXinyuanChartColorMap(keys = [], options = {}) {
return new Map(
Array.from(createXinyuanChartColorMap(keys, options)).map(([key, color]) => [
key,
resolveXinyuanChartColor(color),
]),
);
}
export function getXinyuanEChartsTheme() {
const documentFont = typeof document === 'undefined'
? 'Inter, sans-serif'
: window.getComputedStyle(document.body).fontFamily;
return {
axis: readRootToken('--xinyuan-chart-axis', '#737373'),
fontFamily: documentFont || 'Inter, sans-serif',
foreground: readRootToken('--xinyuan-chart-tooltip-foreground', '#222222'),
grid: readRootToken('--xinyuan-chart-grid', '#e8e8e8'),
label: readRootToken('--xinyuan-chart-label', '#737373'),
palette: Array.from({ length: 16 }, (_, index) => (
readRootToken(`--xinyuan-chart-${index + 1}`, '#667085')
)),
tooltipBackground: readRootToken('--xinyuan-chart-tooltip-background', '#ffffff'),
tooltipBorder: readRootToken('--xinyuan-chart-tooltip-border', '#dedede'),
tooltipShadow: readRootToken(
'--xinyuan-chart-tooltip-shadow',
'0 16px 40px rgb(15 23 42 / 14%)',
),
};
}
function normalizeChartKey(key) { function normalizeChartKey(key) {
return String(key ?? '').trim(); return String(key ?? '').trim();
} }
...@@ -53,13 +108,25 @@ export function getXinyuanChartColor(key, fallbackIndex = 0) { ...@@ -53,13 +108,25 @@ export function getXinyuanChartColor(key, fallbackIndex = 0) {
return XINYUAN_CHART_PALETTE[hashChartKey(stableKey) % XINYUAN_CHART_PALETTE.length]; return XINYUAN_CHART_PALETTE[hashChartKey(stableKey) % XINYUAN_CHART_PALETTE.length];
} }
export function createXinyuanChartColorMap(keys = []) { export function createXinyuanChartColorMap(keys = [], options = {}) {
const stableKeys = [...new Set(keys.map(normalizeChartKey).filter(Boolean))].sort(); const sourceKeys = Array.isArray(keys) ? keys : [];
const orderedKeys = [...new Set(sourceKeys.map(normalizeChartKey).filter(Boolean))];
const order = Array.isArray(options?.order) ? options.order : [];
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;
return leftOrder === rightOrder ? left.localeCompare(right) : leftOrder - rightOrder;
});
const colorMap = new Map(); const colorMap = new Map();
const usedIndexes = new Set(); const usedIndexes = new Set();
stableKeys.forEach((key, keyIndex) => { stableKeys.forEach((key, keyIndex) => {
const preferredIndex = hashChartKey(key) % XINYUAN_CHART_PALETTE.length; const preferredIndex = order.length > 0
? keyIndex % XINYUAN_CHART_PALETTE.length
: hashChartKey(key) % XINYUAN_CHART_PALETTE.length;
let paletteIndex = preferredIndex; let paletteIndex = preferredIndex;
if (keyIndex < XINYUAN_CHART_PALETTE.length) { if (keyIndex < XINYUAN_CHART_PALETTE.length) {
...@@ -78,41 +145,3 @@ export function createXinyuanChartColorMap(keys = []) { ...@@ -78,41 +145,3 @@ export function createXinyuanChartColorMap(keys = []) {
return colorMap; return colorMap;
} }
function isVisibleChartColor(color) {
if (typeof color !== 'string') return false;
const normalizedColor = color.trim().toLowerCase();
return Boolean(normalizedColor)
&& normalizedColor !== 'none'
&& normalizedColor !== 'transparent';
}
export function colorizeXinyuanChartTooltipPayload(payload = [], resolveColor) {
return payload.map((entry, index) => {
const rechartsPayload = entry?.payload || {};
const sourceDatum = rechartsPayload?.payload || rechartsPayload;
const key = sourceDatum?.name
?? rechartsPayload?.name
?? entry?.name
?? entry?.dataKey
?? '';
const candidateColors = [
resolveColor?.({ entry, index, key, sourceDatum }),
rechartsPayload?.fill,
sourceDatum?.fill,
entry?.fill,
entry?.color,
entry?.stroke,
getXinyuanChartColor(key, index),
];
const color = candidateColors.find(isVisibleChartColor);
return {
...entry,
color,
fill: color,
name: entry?.name ?? sourceDatum?.name ?? entry?.dataKey,
stroke: color,
};
});
}
...@@ -452,6 +452,15 @@ ...@@ -452,6 +452,15 @@
gap: var(--rc-page-module-gap); gap: var(--rc-page-module-gap);
} }
.rc-module-title {
margin: 0;
color: var(--rc-text-primary);
font-size: 1rem;
font-weight: var(--rc-font-semibold);
line-height: 1.5rem;
letter-spacing: 0;
}
.rc-page-grid { .rc-page-grid {
min-width: 0; min-width: 0;
gap: var(--rc-page-module-gap); gap: var(--rc-page-module-gap);
...@@ -470,7 +479,7 @@ ...@@ -470,7 +479,7 @@
grid-column: 1 / -1; grid-column: 1 / -1;
} }
/* Recharts keeps keyboard navigation while pointer focus stays visually quiet. */ /* Chart canvases keep keyboard navigation while pointer focus stays visually quiet. */
.rc-chart-interaction:focus:not(:focus-visible), .rc-chart-interaction:focus:not(:focus-visible),
.rc-chart-interaction :focus:not(:focus-visible) { .rc-chart-interaction :focus:not(:focus-visible) {
outline: none; outline: none;
......
...@@ -1237,7 +1237,7 @@ export default function ResourceBookingPage() { ...@@ -1237,7 +1237,7 @@ export default function ResourceBookingPage() {
} }
return ( return (
<div className="space-y-6"> <div className="min-w-0 max-w-full space-y-6">
{resourceError ? ( {resourceError ? (
<Alert status="warning"> <Alert status="warning">
<Alert.Content> <Alert.Content>
...@@ -1292,25 +1292,31 @@ export default function ResourceBookingPage() { ...@@ -1292,25 +1292,31 @@ export default function ResourceBookingPage() {
</Tabs> </Tabs>
</div> </div>
<Surface className="rounded-3xl p-6" variant="default"> <Surface className="w-full min-w-0 max-w-full overflow-visible rounded-3xl p-6" variant="default">
<Disclosure <Disclosure
isExpanded={showAdvancedFilters} isExpanded={showAdvancedFilters}
onExpandedChange={setShowAdvancedFilters} onExpandedChange={setShowAdvancedFilters}
> >
<div className="grid min-w-0 gap-3 xl:grid-cols-[minmax(0,1fr)_auto] xl:items-end"> <div className="grid min-w-0 max-w-full gap-3 overflow-visible 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"> <div className="grid min-w-0 max-w-full grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-[repeat(3,minmax(0,1fr))]">
<TextField fullWidth value={caseSourceFilter} onChange={setCaseSourceFilter}> <div className="w-full min-w-0">
<Label>案例来源</Label> <Label className="mb-1.5 block">案例来源</Label>
<Input fullWidth placeholder="例如:监管通报" variant="secondary" /> <div className="min-w-0">
</TextField> <Input className="w-full min-w-0 max-w-full" fullWidth placeholder="例如:监管通报" variant="secondary" value={caseSourceFilter} onChange={(event) => setCaseSourceFilter(event.target.value)} />
<TextField fullWidth value={caseTypeFilter} onChange={setCaseTypeFilter}> </div>
<Label>案例类型</Label> </div>
<Input fullWidth placeholder="例如:审批绕行" variant="secondary" /> <div className="w-full min-w-0">
</TextField> <Label className="mb-1.5 block">案例类型</Label>
<TextField fullWidth value={caseAttributeFilter} onChange={setCaseAttributeFilter}> <div className="min-w-0">
<Label>问题属性</Label> <Input className="w-full min-w-0 max-w-full" fullWidth placeholder="例如:审批绕行" variant="secondary" value={caseTypeFilter} onChange={(event) => setCaseTypeFilter(event.target.value)} />
<Input fullWidth placeholder="例如:流程绕行" variant="secondary" /> </div>
</TextField> </div>
<div className="w-full min-w-0">
<Label className="mb-1.5 block">问题属性</Label>
<div className="min-w-0">
<Input className="w-full min-w-0 max-w-full" fullWidth placeholder="例如:流程绕行" variant="secondary" value={caseAttributeFilter} onChange={(event) => setCaseAttributeFilter(event.target.value)} />
</div>
</div>
</div> </div>
<div className="flex min-w-0 items-end justify-end"> <div className="flex min-w-0 items-end justify-end">
...@@ -1322,17 +1328,19 @@ export default function ResourceBookingPage() { ...@@ -1322,17 +1328,19 @@ export default function ResourceBookingPage() {
</Disclosure.Trigger> </Disclosure.Trigger>
</div> </div>
<Disclosure.Content <Disclosure.Content
className={clsx( className={clsx(
'min-w-0 xl:col-start-1 xl:col-end-2', 'min-w-0 overflow-visible xl:col-start-1 xl:col-end-2',
!showAdvancedFilters && 'hidden', !showAdvancedFilters && 'hidden',
)} )}
> >
<div className="grid min-w-0 grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3"> <div className="grid min-w-0 max-w-full grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-[repeat(3,minmax(0,1fr))]">
<TextField fullWidth value={tagFilter} onChange={setTagFilter}> <div className="w-full min-w-0">
<Label>分类标签</Label> <Label className="mb-1.5 block">分类标签</Label>
<Input fullWidth placeholder="例如:采购审批" variant="secondary" /> <div className="min-w-0">
</TextField> <Input className="w-full min-w-0 max-w-full" fullWidth placeholder="例如:采购审批" variant="secondary" value={tagFilter} onChange={(event) => setTagFilter(event.target.value)} />
</div>
</div>
</div> </div>
</Disclosure.Content> </Disclosure.Content>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment