chore: auto merge branches (#56323)

chore: merge master into feature
This commit is contained in:
github-actions[bot]
2025-12-23 03:12:41 +00:00
committed by GitHub
20 changed files with 335 additions and 45 deletions

View File

@@ -11,6 +11,7 @@ export const locales = {
suffix: '后缀元素,包含后缀内容的布局和样式,如清除按钮、箭头图标等',
input: '输入框元素,包含搜索输入框的样式、光标控制、字体继承等搜索相关样式,去除了边框样式',
content: '多选容器,包含已选项的布局、间距、换行相关样式',
clear: '清除按钮元素,包含清除按钮的布局、样式和交互效果',
item: '多选项元素,包含边框、背景、内边距、外边距样式',
itemContent: '多选项内容区域,包含文字的省略样式',
itemRemove: '多选项移除按钮,包含字体相关样式',
@@ -29,6 +30,7 @@ export const locales = {
'Input element with search input styling, cursor control, font inheritance and other search-related styles. Remove border styles',
content:
'Multiple selection container with layout, spacing, and wrapping styles for selected items',
clear: 'Clear button element with layout, styling and interactive effects for clear button',
item: 'Multiple selection item element with border, background, padding, and margin styles',
itemContent: 'Multiple selection item content area with text ellipsis styles',
itemRemove: 'Multiple selection item remove button with font-related styles',
@@ -142,6 +144,7 @@ const SelectSemanticTemplate: React.FC<SelectSemanticTemplateProps> = ({
{ name: 'prefix', desc: locale.prefix },
{ name: 'content', desc: locale.content },
{ name: 'placeholder', desc: locale.placeholder },
{ name: 'clear', desc: locale.clear },
{ name: 'input', desc: locale.input },
{ name: 'suffix', desc: locale.suffix },
{ name: 'popup.root', desc: locale['popup.root'] },
@@ -152,11 +155,12 @@ const SelectSemanticTemplate: React.FC<SelectSemanticTemplateProps> = ({
{ name: 'root', desc: locale.root },
{ name: 'prefix', desc: locale.prefix },
{ name: 'content', desc: locale.content },
{ name: 'placeholder', desc: locale.placeholder },
{ name: 'clear', desc: locale.clear },
{ name: 'item', desc: locale.item },
{ name: 'itemContent', desc: locale.itemContent },
{ name: 'itemRemove', desc: locale.itemRemove },
{ name: 'input', desc: locale.input },
{ name: 'placeholder', desc: locale.placeholder },
{ name: 'suffix', desc: locale.suffix },
{ name: 'popup.root', desc: locale['popup.root'] },
{ name: 'popup.list', desc: locale['popup.list'] },

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
if: (github.event.pull_request.head.ref == 'next' || github.event.pull_request.head.ref == 'feature' || github.event.pull_request.head.ref == 'master') && github.event.pull_request.head.user.login == 'ant-design'
steps:
- uses: actions-cool/issues-helper@cbca8dff5d68beaba6fa47e9f49608ed2de544d6
- uses: actions-cool/issues-helper@d1d51fccf39469b5458203b1369060db0ff0c0db
with:
actions: create-comment
issue-number: ${{ github.event.number }}

View File

@@ -4414,3 +4414,52 @@ exports[`renders components/button/demo/style-class.tsx extend context correctly
`;
exports[`renders components/button/demo/style-class.tsx extend context correctly 2`] = `[]`;
exports[`renders components/button/demo/wave.tsx extend context correctly 1`] = `
<div
class="ant-flex css-var-test-id ant-flex-wrap-wrap ant-flex-gap-large"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Disabled
</span>
</button>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Default
</span>
</button>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Inset
</span>
</button>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Shake
</span>
</button>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Happy Work
</span>
</button>
</div>
`;
exports[`renders components/button/demo/wave.tsx extend context correctly 2`] = `[]`;

View File

@@ -3883,3 +3883,50 @@ exports[`renders components/button/demo/style-class.tsx correctly 1`] = `
</button>
</div>
`;
exports[`renders components/button/demo/wave.tsx correctly 1`] = `
<div
class="ant-flex css-var-test-id ant-flex-wrap-wrap ant-flex-gap-large"
>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Disabled
</span>
</button>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Default
</span>
</button>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Inset
</span>
</button>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Shake
</span>
</button>
<button
class="ant-btn css-var-test-id ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span>
Happy Work
</span>
</button>
</div>
`;

View File

@@ -0,0 +1,7 @@
## zh-CN
波纹效果带来了灵动性,你也可以使用 [`@ant-design/happy-work-theme`](https://github.com/ant-design/happy-work-theme) 提供的 HappyProvider 实现动态波纹效果。
## en-US
Wave effect brings dynamic. You can also use HappyProvider from [`@ant-design/happy-work-theme`](https://github.com/ant-design/happy-work-theme) to implement dynamic wave effect.

View File

@@ -0,0 +1,126 @@
import React from 'react';
import { HappyProvider } from '@ant-design/happy-work-theme';
import { Button, ConfigProvider, Flex } from 'antd';
import type { ConfigProviderProps, GetProp } from 'antd';
type WaveConfig = GetProp<ConfigProviderProps, 'wave'>;
// Prepare effect holder
const createHolder = (node: HTMLElement) => {
const { borderWidth } = getComputedStyle(node);
const borderWidthNum = Number.parseInt(borderWidth, 10);
const div = document.createElement('div');
div.style.position = 'absolute';
div.style.inset = `-${borderWidthNum}px`;
div.style.borderRadius = 'inherit';
div.style.background = 'transparent';
div.style.zIndex = '999';
div.style.pointerEvents = 'none';
div.style.overflow = 'hidden';
node.appendChild(div);
return div;
};
const createDot = (holder: HTMLElement, color: string, left: number, top: number, size = 0) => {
const dot = document.createElement('div');
dot.style.position = 'absolute';
dot.style.left = `${left}px`;
dot.style.top = `${top}px`;
dot.style.width = `${size}px`;
dot.style.height = `${size}px`;
dot.style.borderRadius = '50%';
dot.style.background = color;
dot.style.transform = 'translate3d(-50%, -50%, 0)';
dot.style.transition = 'all 1s ease-out';
holder.appendChild(dot);
return dot;
};
// Inset Effect
const showInsetEffect: WaveConfig['showEffect'] = (node, { event, component }) => {
if (component !== 'Button') {
return;
}
const holder = createHolder(node);
const rect = holder.getBoundingClientRect();
const left = event.clientX - rect.left;
const top = event.clientY - rect.top;
const dot = createDot(holder, 'rgba(255, 255, 255, 0.65)', left, top);
// Motion
requestAnimationFrame(() => {
dot.ontransitionend = () => {
holder.remove();
};
dot.style.width = '200px';
dot.style.height = '200px';
dot.style.opacity = '0';
});
};
// Shake Effect
const showShakeEffect: WaveConfig['showEffect'] = (node, { component }) => {
if (component !== 'Button') {
return;
}
const seq = [0, -15, 15, -5, 5, 0];
const itv = 10;
let steps = 0;
const loop = () => {
cancelAnimationFrame((node as any).effectTimeout);
(node as any).effectTimeout = requestAnimationFrame(() => {
const currentStep = Math.floor(steps / itv);
const current = seq[currentStep];
const next = seq[currentStep + 1];
if (next === undefined || next === null) {
node.style.transform = '';
node.style.transition = '';
return;
}
// Trans from current to next by itv
const angle = current + ((next - current) / itv) * (steps % itv);
node.style.transform = `rotate(${angle}deg)`;
node.style.transition = 'none';
steps += 1;
loop();
});
};
loop();
};
// Component
const Wrapper: React.FC<WaveConfig & { name: string }> = ({ name, ...wave }) => (
<ConfigProvider wave={wave}>
<Button type="primary">{name}</Button>
</ConfigProvider>
);
const Demo: React.FC = () => (
<Flex gap="large" wrap>
<Wrapper name="Disabled" disabled />
<Wrapper name="Default" />
<Wrapper name="Inset" showEffect={showInsetEffect} />
<Wrapper name="Shake" showEffect={showShakeEffect} />
<HappyProvider>
<Button type="primary">Happy Work</Button>
</HappyProvider>
</Flex>
);
export default Demo;

View File

@@ -52,6 +52,7 @@ And 4 other properties additionally.
<code src="./demo/chinese-chars-loading.tsx" debug>Loading style bug</code>
<code src="./demo/component-token.tsx" debug>Component Token</code>
<code src="./demo/linear-gradient.tsx">Gradient Button</code>
<code src="./demo/wave.tsx">Custom Wave</code>
<code src="./demo/custom-disabled-bg.tsx">Custom disabled backgroundColor</code>
<code src="./demo/style-class.tsx" version="6.0.0">Custom semantic dom styling</code>

View File

@@ -53,6 +53,7 @@ group:
<code src="./demo/chinese-chars-loading.tsx" debug>加载中状态 bug 还原</code>
<code src="./demo/component-token.tsx" debug>组件 Token</code>
<code src="./demo/linear-gradient.tsx">渐变按钮</code>
<code src="./demo/wave.tsx">自定义按钮波纹</code>
<code src="./demo/chinese-space.tsx" version="5.17.0">移除两个汉字之间的空格</code>
<code src="./demo/custom-disabled-bg.tsx">自定义禁用样式背景</code>
<code src="./demo/style-class.tsx" version="6.0.0">自定义语义结构的样式和类</code>

View File

@@ -181,11 +181,6 @@ export interface ComponentToken {
* @descEN Icon size of small button which only contains icon
*/
onlyIconSizeSM: number | string;
/**
* @desc 按钮组边框颜色
* @descEN Border color of button group
*/
groupBorderColor: string;
/**
* @desc 链接按钮悬浮态背景色
* @descEN Background color of link button when hover
@@ -246,7 +241,17 @@ type ShadowColorMap = {
[Key in `${PresetColorKey}ShadowColor`]: string;
};
export interface ButtonToken extends FullToken<'Button'>, ShadowColorMap {
type GroupToken = {
/**
* @desc 按钮组边框颜色
* @descEN Border color of button group
* @internal Button.Group 已废弃相关token不应该在显示在文档上
*/
groupBorderColor: string;
};
export interface ButtonToken extends FullToken<'Button'>, ShadowColorMap, GroupToken {
/**
* @desc 按钮横向内边距
* @descEN Horizontal padding of button

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { HappyProvider } from '@ant-design/happy-work-theme';
import { Button, ConfigProvider, Space } from 'antd';
import { Button, ConfigProvider, Flex } from 'antd';
import type { ConfigProviderProps, GetProp } from 'antd';
type WaveConfig = GetProp<ConfigProviderProps, 'wave'>;
@@ -32,10 +32,9 @@ const createDot = (holder: HTMLElement, color: string, left: number, top: number
dot.style.height = `${size}px`;
dot.style.borderRadius = '50%';
dot.style.background = color;
dot.style.transform = 'translate(-50%, -50%)';
dot.style.transform = 'translate3d(-50%, -50%, 0)';
dot.style.transition = 'all 1s ease-out';
holder.appendChild(dot);
return dot;
};
@@ -77,7 +76,7 @@ const showShakeEffect: WaveConfig['showEffect'] = (node, { component }) => {
let steps = 0;
function loop() {
const loop = () => {
cancelAnimationFrame((node as any).effectTimeout);
(node as any).effectTimeout = requestAnimationFrame(() => {
@@ -85,7 +84,7 @@ const showShakeEffect: WaveConfig['showEffect'] = (node, { component }) => {
const current = seq[currentStep];
const next = seq[currentStep + 1];
if (!next) {
if (next === undefined || next === null) {
node.style.transform = '';
node.style.transition = '';
return;
@@ -100,20 +99,20 @@ const showShakeEffect: WaveConfig['showEffect'] = (node, { component }) => {
steps += 1;
loop();
});
}
};
loop();
};
// Component
const Wrapper = ({ name, ...wave }: WaveConfig & { name: string }) => (
const Wrapper: React.FC<WaveConfig & { name: string }> = ({ name, ...wave }) => (
<ConfigProvider wave={wave}>
<Button type="primary">{name}</Button>
</ConfigProvider>
);
const App = () => (
<Space style={{ padding: 24 }} size="large">
const Demo: React.FC = () => (
<Flex gap="large" wrap>
<Wrapper name="Disabled" disabled />
<Wrapper name="Default" />
<Wrapper name="Inset" showEffect={showInsetEffect} />
@@ -121,7 +120,7 @@ const App = () => (
<HappyProvider>
<Button type="primary">Happy Work</Button>
</HappyProvider>
</Space>
</Flex>
);
export default App;
export default Demo;

View File

@@ -6,8 +6,19 @@ const onChange: InputNumberProps['onChange'] = (value) => {
console.log('changed', value);
};
const onStep: InputNumberProps['onStep'] = (value, info) => {
console.log('onStep', value, info);
};
const App: React.FC = () => (
<InputNumber min={1} max={10} defaultValue={3} onChange={onChange} changeOnWheel />
<InputNumber
min={1}
max={10}
defaultValue={3}
onChange={onChange}
onStep={onStep}
changeOnWheel
/>
);
export default App;

View File

@@ -71,7 +71,7 @@ Common props ref[Common props](/docs/react/common-props)
| variant | Variants of Input | `outlined` \| `borderless` \| `filled` \| `underlined` | `outlined` | 5.13.0 \| `underlined`: 5.24.0 |
| onChange | The callback triggered when the value is changed | function(value: number \| string \| null) | - | - |
| onPressEnter | The callback function that is triggered when Enter key is pressed | function(e) | - | - |
| onStep | The callback function that is triggered when click up or down buttons | (value: number, info: { offset: number, type: 'up' \| 'down' }) => void | - | |
| onStep | The callback function that is triggered when click up or down buttons / Keyboard / Wheel | (value: number, info: { offset: number, type: 'up' \| 'down', emitter: 'handler' \| 'keydown' \| 'wheel' }) => void | - | |
## Ref

View File

@@ -72,7 +72,7 @@ demo:
| variant | 形态变体 | `outlined` \| `borderless` \| `filled` \| `underlined` | `outlined` | 5.13.0 \| `underlined`: 5.24.0 |
| onChange | 变化回调 | function(value: number \| string \| null) | - | - |
| onPressEnter | 按下回车的回调 | function(e) | - | - |
| onStep | 点击上下箭头的回调 | (value: number, info: { offset: number, type: 'up' \| 'down' }) => void | - | 4.7.0 |
| onStep | 点击上下箭头、键盘、滚轮的回调 | (value: number, info: { offset: number, type: 'up' \| 'down', emitter: 'handler' \| 'keydown' \| 'wheel' }) => void | - | 4.7.0 |
## Ref

View File

@@ -13,6 +13,7 @@ export interface GeneratorProps {
tagName: 'header' | 'footer' | 'main' | 'div';
displayName: string;
}
export interface BasicProps extends React.HTMLAttributes<HTMLDivElement> {
prefixCls?: string;
suffixCls?: string;
@@ -24,17 +25,17 @@ interface BasicPropsWithTagName extends BasicProps {
tagName: 'header' | 'footer' | 'main' | 'div';
}
function generator({ suffixCls, tagName, displayName }: GeneratorProps) {
return (BasicComponent: any) => {
const generator = ({ suffixCls, tagName, displayName }: GeneratorProps) => {
return (Component: React.ComponentType<BasicPropsWithTagName & React.RefAttributes<any>>) => {
const Adapter = React.forwardRef<HTMLElement, BasicProps>((props, ref) => (
<BasicComponent ref={ref} suffixCls={suffixCls} tagName={tagName} {...props} />
<Component ref={ref} suffixCls={suffixCls} tagName={tagName} {...props} />
));
if (process.env.NODE_ENV !== 'production') {
Adapter.displayName = displayName;
}
return Adapter;
};
}
};
const Basic = React.forwardRef<HTMLDivElement, BasicPropsWithTagName>((props, ref) => {
const {

View File

@@ -1,7 +1,7 @@
import * as React from 'react';
import Select from '..';
import type { SelectProps } from '..';
import type { SelectClassNamesType, SelectProps } from '..';
import { render } from '../../../tests/utils';
describe('Select.Semantic', () => {
@@ -28,7 +28,7 @@ describe('Select.Semantic', () => {
list: 'custom-list',
listItem: 'custom-list-item',
},
};
} satisfies SelectClassNamesType;
const styles = {
root: { color: 'rgb(255, 0, 0)' },
prefix: { color: 'rgb(0, 128, 255)' },
@@ -60,9 +60,9 @@ describe('Select.Semantic', () => {
expect(container.querySelector(`.${classNames.placeholder}`)).toHaveStyle(styles.placeholder);
expect(container.querySelector(`.${classNames.input}`)).toHaveStyle(styles.input);
expect(container.querySelector(`.${classNames.content}`)).toHaveStyle(styles.content);
expect(container.querySelector(`.${classNames.popup.root}`)).toHaveStyle(styles.popup.root);
expect(container.querySelector(`.${classNames.popup.list}`)).toHaveStyle(styles.popup.list);
expect(container.querySelector(`.${classNames.popup.listItem}`)).toHaveStyle(
expect(container.querySelector(`.${classNames.popup?.root}`)).toHaveStyle(styles.popup.root);
expect(container.querySelector(`.${classNames.popup?.list}`)).toHaveStyle(styles.popup.list);
expect(container.querySelector(`.${classNames.popup?.listItem}`)).toHaveStyle(
styles.popup.listItem,
);
});
@@ -72,16 +72,22 @@ describe('Select.Semantic', () => {
root: 'custom-root',
prefix: 'custom-prefix',
suffix: 'custom-suffix',
item: 'custom-item',
itemContent: 'custom-item-content',
itemRemove: 'custom-item-remove',
popup: {
root: 'custom-popup',
list: 'custom-list',
listItem: 'custom-list-item',
},
};
} satisfies SelectClassNamesType;
const customStyles = {
root: { color: 'rgb(255, 0, 0)' },
prefix: { color: 'rgb(0, 128, 255)' },
suffix: { color: 'rgb(255, 128, 0)' },
item: { background: 'rgb(255, 255, 240)' },
itemContent: { color: 'rgb(128, 0, 128)' },
itemRemove: { color: 'rgb(255, 0, 0)' },
popup: {
root: { color: 'rgb(128, 0, 128)' },
list: { color: 'rgb(0, 0, 255)' },
@@ -107,6 +113,9 @@ describe('Select.Semantic', () => {
const list = container.querySelector('.rc-virtual-list');
const listItem = container.querySelector('.ant-select-item');
const popup = container.querySelector('.ant-select-dropdown');
const item = container.querySelector('.ant-select-selection-item');
const itemContent = container.querySelector('.ant-select-selection-item-content');
const itemRemove = container.querySelector('.ant-select-selection-item-remove');
expect(root).toHaveClass(customClassNames.root);
expect(prefix).toHaveClass(customClassNames.prefix);
@@ -120,6 +129,15 @@ describe('Select.Semantic', () => {
if (popup) {
expect(popup).toHaveClass(customClassNames.popup.root);
}
if (item) {
expect(item).toHaveClass(customClassNames.item);
}
if (itemContent) {
expect(itemContent).toHaveClass(customClassNames.itemContent);
}
if (itemRemove) {
expect(itemRemove).toHaveClass(customClassNames.itemRemove);
}
expect(root).toHaveStyle(customStyles.root);
expect(prefix).toHaveStyle(customStyles.prefix);
@@ -133,6 +151,15 @@ describe('Select.Semantic', () => {
if (popup) {
expect(popup).toHaveStyle(customStyles.popup.root);
}
if (item) {
expect(item).toHaveStyle(customStyles.item);
}
if (itemContent) {
expect(itemContent).toHaveStyle(customStyles.itemContent);
}
if (itemRemove) {
expect(itemRemove).toHaveStyle(customStyles.itemRemove);
}
});
it('should support function-based classNames and styles', () => {

View File

@@ -71,18 +71,30 @@ export interface InternalSelectProps<
styles?: SelectSemanticStyles & { popup?: PopupSemanticStyles };
}
export type SelectSemanticName = 'root' | 'prefix' | 'suffix';
export type SelectSemanticClassNames = {
root?: string;
prefix?: string;
suffix?: string;
input?: string;
placeholder?: string;
content?: string;
item?: string;
itemContent?: string;
itemRemove?: string;
clear?: string;
};
export type SelectSemanticStyles = {
root?: React.CSSProperties;
prefix?: React.CSSProperties;
suffix?: React.CSSProperties;
input?: React.CSSProperties;
placeholder?: React.CSSProperties;
content?: React.CSSProperties;
item?: React.CSSProperties;
itemContent?: React.CSSProperties;
itemRemove?: React.CSSProperties;
clear?: React.CSSProperties;
};
export type PopupSemanticClassNames = {

View File

@@ -38,7 +38,7 @@ const ListItem = <RecordType extends KeyWiseTransferItem>(props: ListItemProps<R
const mergedDisabled = disabled || item?.disabled;
const classes = clsx(`${prefixCls}-content-item`, classNames.item, {
[`${prefixCls}-content-item-disabled`]: mergedDisabled,
[`${prefixCls}-content-item-checked`]: checked && !item.disabled,
[`${prefixCls}-content-item-checked`]: checked && !mergedDisabled,
});
let title: string | undefined;

View File

@@ -47,12 +47,12 @@ Ant Design 的图标设计对于设计稿的分层也有一定的要求,其目
<img class="preview-img no-padding" src="https://gw.alipayobjects.com/zos/rmsportal/bVtUZqDRbGuaoVbwYqua.png" alt="分层">
</div>
## 轮廓线与模
## 轮廓线与模
我们对设计模进行了优化,根据出血位的尺寸,调整轮廓线的宽高,同时增加两个等边三角形和一个圆,这些都是图标设计中最常用的基本形式,设计师可以快速的调用并在此基础上做变形。
我们对设计模进行了优化,根据出血位的尺寸,调整轮廓线的宽高,同时增加两个等边三角形和一个圆,这些都是图标设计中最常用的基本形式,设计师可以快速的调用并在此基础上做变形。
<div>
<img class="preview-img no-padding" src="https://gw.alipayobjects.com/zos/rmsportal/ycDkLxfAqjnRsWZuHvik.png" alt="轮廓线与模">
<img class="preview-img no-padding" src="https://gw.alipayobjects.com/zos/rmsportal/ycDkLxfAqjnRsWZuHvik.png" alt="轮廓线与模">
</div>
## 图标设计指引

View File

@@ -52,7 +52,7 @@ title: 列表页
将数据过滤模块放置在侧栏,当过滤条件过多,横向空间充裕时使用。
#### [模 - 查询表格](https://preview.pro.ant.design/list/table-list)
#### [模 - 查询表格](https://preview.pro.ant.design/list/table-list)
<ImagePreview>
<img class="preview-img no-padding" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*uAGRTY5EMvIAAAAAAAAAAABkARQnAQ">
@@ -62,7 +62,7 @@ title: 列表页
每个条目都需要露出很多字段;用户在搜寻条目时有准确的查询范围时使用。
#### 模 - 标准列表
#### 模 - 标准列表
<ImagePreview>
<img class="preview-img no-padding" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*3KMbRrbjvzkAAAAAAAAAAABkARQnAQ">
@@ -82,7 +82,7 @@ title: 列表页
用户无需以特定顺序浏览条目,将每个条目以富有吸引力的方式呈现。
#### 模 - 搜索列表
#### 模 - 搜索列表
<ImagePreview>
<img class="preview-img no-padding" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*yW4QQKNi_0QAAAAAAAAAAABkARQnAQ">
@@ -96,7 +96,7 @@ title: 列表页
筛选、搜索
#### 模 - 成员管理
#### 模 - 成员管理
<ImagePreview>
<img class="preview-img no-padding" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*aJxDR6oP19gAAAAAAAAAAABkARQnAQ">

View File

@@ -122,7 +122,7 @@
"@rc-component/dialog": "~1.6.0",
"@rc-component/drawer": "~1.3.0",
"@rc-component/dropdown": "~1.0.2",
"@rc-component/form": "~1.5.0",
"@rc-component/form": "~1.6.0",
"@rc-component/image": "~1.5.3",
"@rc-component/input": "~1.1.2",
"@rc-component/input-number": "~1.6.2",
@@ -224,7 +224,7 @@
"ajv": "^8.17.1",
"ali-oss": "^6.23.0",
"antd-img-crop": "^4.27.0",
"antd-style": "4.0.0-alpha.1",
"antd-style": "^4.0.0-beta.1",
"antd-token-previewer": "^3.0.0",
"axios": "^1.13.2",
"chalk": "^5.6.2",
@@ -247,7 +247,7 @@
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24",
"fast-glob": "^3.3.3",
"father": "4.6.10",
"father": "4.6.11",
"fs-extra": "^11.3.2",
"gh-pages": "^6.3.0",
"github-slugger": "^2.0.0",