1+ using Microsoft . AspNetCore . Components . Rendering ;
2+
3+ namespace TDesign ;
4+ /// <summary>
5+ /// 骨架屏。当网络较慢时,在页面真实数据加载之前,给用户展示出页面的大致结构。
6+ /// </summary>
7+ [ ParentComponent ]
8+ [ CssClass ( "t-skeleton" ) ]
9+ public class TSkeleton : BlazorComponentBase , IHasChildContent
10+ {
11+ /// <summary>
12+ /// 设置是否显示骨架屏。
13+ /// </summary>
14+ [ Parameter ] [ EditorRequired ] public bool Loading { get ; set ; }
15+ /// <summary>
16+ /// 当 <see cref="Loading"/> 是 <c>false</c> 时显示的内容。
17+ /// </summary>
18+ [ Parameter ] public RenderFragment ? ChildContent { get ; set ; }
19+ /// <summary>
20+ /// 当 <see cref="Loading"/> 是 <c>true</c> 时显示的内容。
21+ /// </summary>
22+ [ Parameter ] public RenderFragment ? LoadingContent { get ; set ; }
23+
24+ /// <summary>
25+ /// 设置动画效果。
26+ /// </summary>
27+ [ Parameter ] public SkeletonAnimation ? Animation { get ; set ; }
28+
29+
30+ /// <summary>
31+ /// 设置骨架屏的模式。可以快速设置骨架屏显示的模式。
32+ /// </summary>
33+ [ Parameter ] public SkeletonTheme ? Theme { get ; set ; } = SkeletonTheme . Paragraph ;
34+
35+ /// <inheritdoc/>
36+ protected override void OnParametersSet ( )
37+ {
38+ base . OnParametersSet ( ) ;
39+
40+ if ( Theme is not null && LoadingContent is null )
41+ {
42+ LoadingContent = GetThemeContent ( ) ;
43+ }
44+ }
45+
46+ /// <inheritdoc/>
47+ protected override void AddContent ( RenderTreeBuilder builder , int sequence )
48+ {
49+ if ( Loading )
50+ {
51+ builder . AddContent ( sequence , LoadingContent ) ;
52+ }
53+ else
54+ {
55+ base . AddContent ( builder , sequence ) ;
56+ }
57+ }
58+
59+ /// <summary>
60+ /// 获取主题对应的骨架屏。
61+ /// </summary>
62+ RenderFragment GetThemeContent ( )
63+ => Theme switch
64+ {
65+ SkeletonTheme . Text => builder => builder . CreateComponent < TSkeletonRow > ( 0 , col => col . CreateComponent < TSkeletonColumn > ( 0 ) ) ,
66+ SkeletonTheme . Paragraph => builder =>
67+ {
68+ builder . CreateComponent < TSkeletonRow > ( 0 , col => col . CreateComponent < TSkeletonColumn > ( 0 ) ) ;
69+ builder . CreateComponent < TSkeletonRow > ( 1 , col => col . CreateComponent < TSkeletonColumn > ( 0 ) ) ;
70+ builder . CreateComponent < TSkeletonRow > ( 2 , col => col . CreateComponent < TSkeletonColumn > ( 0 ) ) ;
71+ }
72+ ,
73+ SkeletonTheme . Avatar => builder => builder . CreateComponent < TSkeletonRow > ( 0 , col => col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { Type = SkeletonColumnType . Circle , style = "height:56px;width:56px" } ) ) ,
74+ SkeletonTheme . AvatarText => builder => builder . CreateComponent < TSkeletonRow > ( 0 , col =>
75+ {
76+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { Type = SkeletonColumnType . Circle } ) ;
77+ col . CreateComponent < TSkeletonColumn > ( 1 , attributes : new { style = "height:32px" } ) ;
78+ } ) ,
79+ SkeletonTheme . Tab => builder =>
80+ {
81+ builder . CreateComponent < TSkeletonRow > ( 0 , col => col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ) ;
82+ builder . CreateComponent < TSkeletonRow > ( 0 , col => col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:200px" } ) ) ;
83+ }
84+ ,
85+ SkeletonTheme . Article => builder =>
86+ {
87+ builder . CreateComponent < TSkeletonRow > ( 0 , col => col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "width:100%;height:30px" } ) ) ;
88+ builder . CreateComponent < TSkeletonRow > ( 0 , col => col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "width:100%;height:200px" } ) ) ;
89+
90+ builder . CreateComponent < TSkeletonRow > ( 0 , col =>
91+ {
92+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
93+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
94+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
95+ } ) ;
96+
97+ builder . CreateComponent < TSkeletonRow > ( 0 , col =>
98+ {
99+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
100+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
101+ } ) ;
102+
103+ builder . CreateComponent < TSkeletonRow > ( 0 , col =>
104+ {
105+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
106+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
107+ } ) ;
108+
109+ builder . CreateComponent < TSkeletonRow > ( 0 , col =>
110+ {
111+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
112+ col . CreateComponent < TSkeletonColumn > ( 0 , attributes : new { style = "height:30px" } ) ;
113+ } ) ;
114+ }
115+ ,
116+ _ => builder => { }
117+ } ;
118+ }
119+ /// <summary>
120+ /// 表示骨架屏中的行。
121+ /// </summary>
122+ [ ChildComponent ( typeof ( TSkeleton ) ) ]
123+ [ ParentComponent ]
124+ [ CssClass ( "t-skeleton__row" ) ]
125+ public class TSkeletonRow : BlazorComponentBase , IHasChildContent
126+ {
127+
128+ /// <inheritdoc/>
129+ [ Parameter ] public RenderFragment ? ChildContent { get ; set ; }
130+
131+ }
132+
133+ /// <summary>
134+ /// 表示骨架屏中的行。
135+ /// </summary>
136+ [ ChildComponent ( typeof ( TSkeleton ) ) ]
137+ [ ChildComponent ( typeof ( TSkeletonRow ) ) ]
138+ [ CssClass ( "t-skeleton__col" ) ]
139+ public class TSkeletonColumn : BlazorComponentBase
140+ {
141+
142+ /// <summary>
143+ /// 获取 <see cref="TSkeleton"/> 组件。
144+ /// </summary>
145+ [ CascadingParameter ] public TSkeleton ? CascadingSkeleton { get ; set ; }
146+
147+ /// <summary>
148+ /// 设置列的类型。
149+ /// </summary>
150+ [ Parameter ] [ CssClass ( "t-skeleton--type-" ) ] public SkeletonColumnType Type { get ; set ; } = SkeletonColumnType . Text ;
151+
152+ /// <inheritdoc/>
153+ protected override void BuildCssClass ( ICssClassBuilder builder )
154+ {
155+ builder . Append ( $ "t-skeleton--animation-{ CascadingSkeleton ? . Animation ? . GetCssClass ( ) } ", CascadingSkeleton ? . Animation is not null ) ;
156+ }
157+ }
158+ /// <summary>
159+ /// 骨架屏列的类型。
160+ /// </summary>
161+ public enum SkeletonColumnType
162+ {
163+ /// <summary>
164+ /// 长方形。
165+ /// </summary>
166+ [ CssClass ( "rect" ) ] Rectangle ,
167+ /// <summary>
168+ /// 圆形。
169+ /// </summary>
170+ Circle ,
171+ /// <summary>
172+ /// 文本。
173+ /// </summary>
174+ Text
175+ }
176+ /// <summary>
177+ /// 骨架屏的动画效果。
178+ /// </summary>
179+ public enum SkeletonAnimation
180+ {
181+ /// <summary>
182+ /// 渐变效果。
183+ /// </summary>
184+ Gradient ,
185+ /// <summary>
186+ /// 闪烁效果。
187+ /// </summary>
188+ Flashed
189+ }
190+ /// <summary>
191+ /// 骨架屏主题模式。
192+ /// </summary>
193+ public enum SkeletonTheme
194+ {
195+ /// <summary>
196+ /// 文本。
197+ /// </summary>
198+ Text ,
199+ /// <summary>
200+ /// 段落。
201+ /// </summary>
202+ Paragraph ,
203+ /// <summary>
204+ /// 头像。
205+ /// </summary>
206+ Avatar ,
207+ /// <summary>
208+ /// 头像文本。
209+ /// </summary>
210+ AvatarText ,
211+ /// <summary>
212+ /// 选项卡。
213+ /// </summary>
214+ Tab ,
215+ /// <summary>
216+ /// 长篇文章。
217+ /// </summary>
218+ Article
219+ }
0 commit comments