1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+ < head >
4+ < meta charset ="UTF-8 ">
5+ < title > ObjectUI Generic Renderer</ title >
6+ < style >
7+ body { font-family : -apple-system, sans-serif; padding : 20px ; background : # f4f6f8 ; }
8+ .ui-card { background : white; padding : 20px ; border-radius : 8px ; box-shadow : 0 2px 4px rgba (0 , 0 , 0 , 0.1 ); }
9+ h2 { margin-top : 0 ; }
10+ table { width : 100% ; border-collapse : collapse; margin-top : 15px ; }
11+ th , td { text-align : left; padding : 12px ; border-bottom : 1px solid # eee ; }
12+ th { background : # fafafa ; color : # 666 ; font-weight : 600 ; }
13+ .badge { padding : 4px 8px ; border-radius : 12px ; font-size : 12px ; }
14+ .badge-done { background : # e3fcef ; color : # 0d7f56 ; }
15+ .badge-todo { background : # fff8c5 ; color : # 9a6700 ; }
16+ </ style >
17+ </ head >
18+ < body >
19+
20+ < div id ="app " class ="ui-card ">
21+ < div > Loading ObjectUI...</ div >
22+ </ div >
23+
24+ <!-- 模拟 ObjectUI SDK -->
25+ < script >
26+ // 模拟 API Client (在真实场景中调用实际 Server 端口)
27+ const mockApi = {
28+ // 1. 获取对象的定义 (Schema)
29+ getMeta : async ( object ) => {
30+ // 模拟 Server 返回 (对应 DataEngine.getMetadata)
31+ return {
32+ name : 'todo' ,
33+ label : 'Task Manager' ,
34+ fields : {
35+ title : { type : 'text' , label : 'Task Name' } ,
36+ status : { type : 'select' , label : 'Current Status' , options : [ 'Todo' , 'Done' ] } ,
37+ priority : { type : 'number' , label : 'Priority Level' }
38+ }
39+ } ;
40+ } ,
41+ // 2. 获取视图配置 (View Protocol)
42+ getView : async ( object ) => {
43+ // 模拟 Server 返回 (对应 DataEngine.getView)
44+ return {
45+ type : 'datagrid' ,
46+ columns : [
47+ { field : 'title' , width : 200 } ,
48+ { field : 'status' , widget : 'badge' } ,
49+ { field : 'priority' }
50+ ]
51+ } ;
52+ } ,
53+ // 3. 获取数据
54+ getData : async ( object ) => {
55+ // 模拟 ObjectQL 查询结果
56+ return [
57+ { id : 1 , title : 'Refactor DataEngine' , status : 'Done' , priority : 1 } ,
58+ { id : 2 , title : 'Implement ObjectUI' , status : 'Todo' , priority : 2 } ,
59+ { id : 3 , title : 'Write Documentation' , status : 'Todo' , priority : 3 }
60+ ] ;
61+ }
62+ } ;
63+
64+ // ObjectUI 核心渲染器
65+ class ObjectUIRenderer {
66+ constructor ( containerId ) {
67+ this . container = document . getElementById ( containerId ) ;
68+ }
69+
70+ async renderList ( objectName ) {
71+ this . container . innerHTML = 'Fetching Protocol & Data...' ;
72+
73+ // 并行加载:元数据 + 视图定义 + 实际数据
74+ const [ meta , view , data ] = await Promise . all ( [
75+ mockApi . getMeta ( objectName ) ,
76+ mockApi . getView ( objectName ) ,
77+ mockApi . getData ( objectName )
78+ ] ) ;
79+
80+ // 渲染逻辑
81+ let html = `<h2>${ meta . label || objectName } </h2>` ;
82+ html += `<table><thead><tr>` ;
83+
84+ // 1. 动态生成表头 (根据 View Protocol)
85+ view . columns . forEach ( col => {
86+ // 如果 View 没通过 label,就去 Schema 里找
87+ const fieldConfig = meta . fields [ col . field ] || { } ;
88+ const label = col . label || fieldConfig . label || col . field ;
89+ html += `<th>${ label } </th>` ;
90+ } ) ;
91+ html += `</tr></thead><tbody>` ;
92+
93+ // 2. 动态生成数据行
94+ data . forEach ( row => {
95+ html += `<tr>` ;
96+ view . columns . forEach ( col => {
97+ const val = row [ col . field ] ;
98+ const fieldConfig = meta . fields [ col . field ] || { } ;
99+
100+ // 3. 智能组件渲染 (Widget System)
101+ let cellContent = val ;
102+
103+ // 根据 Schema 类型或 View 组件进行特殊渲染
104+ if ( col . widget === 'badge' || fieldConfig . type === 'select' ) {
105+ const badgeClass = `badge-${ String ( val ) . toLowerCase ( ) } ` ;
106+ cellContent = `<span class="badge ${ badgeClass } ">${ val } </span>` ;
107+ }
108+
109+ html += `<td>${ cellContent } </td>` ;
110+ } ) ;
111+ html += `</tr>` ;
112+ } ) ;
113+
114+ html += `</tbody></table>` ;
115+ this . container . innerHTML = html ;
116+ }
117+ }
118+
119+ // 启动应用
120+ const ui = new ObjectUIRenderer ( 'app' ) ;
121+ ui . renderList ( 'todo' ) ; // 只需要名字,剩下的全靠元数据驱动
122+
123+ </ script >
124+ </ body >
125+ </ html >
0 commit comments