Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
testzg001
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
template admin
testzg001
Commits
0b8505a1
Commit
0b8505a1
authored
Nov 04, 2025
by
sunboylu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: test null03
parent
d5442ef7
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
231 additions
and
0 deletions
+231
-0
ARCHITECTURE_testzg001.md
ARCHITECTURE_testzg001.md
+202
-0
air_testzg001.js
assets/testzg001/script/air_testzg001.js
+29
-0
No files found.
ARCHITECTURE_testzg001.md
0 → 100644
View file @
0b8505a1
# TestZG001 项目架构与关键函数示例
## 项目总览
-
目标:在 Cocos Creator 环境中,通过 GameCenter 展示课程卡片,点击后动态加载对应模板(Bundle)并运行场景。
-
平台:iOS / Android / Web Desktop(按平台选择不同的模板目录与版本)。
-
关键模块:GameCenter(页面控制)、GameCard(卡片渲染与交互)、middleLayer(模板加载与运行层)、工具与发布脚本。
## 目录结构
```
root
├── assets/testzg001/
│ ├── pages/gamecenter/ # 页面层(GameCenter、GameCard、prefab、scene等)
│ ├── script/ # 业务与运行层(middleLayer、util、air等)
│ ├── scene/ # 场景资源
│ ├── textures|audios|fonts|dragonBones # 素材资源
│ └── *.meta # 资源元数据
├── bin/ # 构建与发布脚本
├── packages/ # 项目工具插件(校验命名、替换UUID、引用查找器)
├── form/、form_angular/ # 发布与表单UI
├── settings/、project.json # 工程配置
└── tsconfig.json # TypeScript 编译配置
```
## 核心模块
-
GameCenter(assets/testzg001/pages/gamecenter/gamecenter_testzg001.ts)
-
展示课程卡片列表,处理点击,调用 middleLayer 加载模板与场景。
-
覆盖 middleLayer 的进度更新以驱动 UI。
-
GameCard(assets/testzg001/pages/gamecenter/gamecard_testzg001.ts)
-
组件:渲染单个卡片,
`init(data)`
初始化显示与交互。
-
middleLayer(assets/testzg001/script/middleLayer_testzg001.ts)
-
通过
`config.json`
决定
`sceneName`
、
`version`
与
`bundle`
路径。
-
封装
`cc.assetManager.loadBundle`
与
`bundle.loadScene`
,处理进度、错误、运行场景。
-
提供关闭按钮、日志输出、资源清理等能力。
## 关键流程总览
1.
GameCenter 初始化 → 渲染列表 → 用户点击卡片。
2.
调用
`middleLayer.loadPageBundle(courseItem, cb)`
获取模板配置并选择平台路径。
3.
`middleLayer.loadBundle(sceneName, version, bondleUrl, cb)`
加载 Bundle 与 Scene。
4.
进度回调更新 UI → 场景运行 → 显示关闭按钮与交互。
5.
退出时清理资源。
## 关键函数调用逻辑与示例
### 1) GameCenter → middleLayer 加载模板
```
ts
// 假设已拿到 middleLayerComp 与 courseItem
middleLayerComp
.
loadPageBundle
(
courseItem
,
(
err
?:
any
)
=>
{
if
(
err
)
{
console
.
error
(
'
模板加载失败
'
,
err
);
return
;
}
console
.
log
(
'
模板加载完成,场景已运行
'
);
});
```
### 2) 覆盖进度更新(overrideProgressUpdate)
```
ts
private
overrideProgressUpdate
(
middleLayerComp
:
any
)
{
const
original
=
middleLayerComp
.
setLoadingProgressBar
.
bind
(
middleLayerComp
);
// 将 middleLayer 的进度回调输出到 GameCenter 的 UI
middleLayerComp
.
setLoadingProgressBar
=
(
progress
:
number
)
=>
{
// 示例:映射到页面的进度条与文本
if
(
this
.
progressLabel
)
this
.
progressLabel
.
string
=
`加载进度:
${
progress
}
%`
;
if
(
this
.
progressBar
)
this
.
progressBar
.
progress
=
progress
/
100
;
// 保留原逻辑(如内部日志/动画)
original
(
progress
);
};
}
```
### 3) GameCard 组件初始化
```
ts
// 通过 prefab 实例化卡片后,确保拿到组件并初始化数据
const
cardNode
=
cc
.
instantiate
(
this
.
gameCardPrefab
);
const
gameCardComp
=
cardNode
.
getComponent
(
GameCard
)
||
cardNode
.
addComponent
(
GameCard
);
// 确保 GameCardData 要求的 cw_cover 存在;没有则使用 cover 兜底
const
cardData
:
GameCardData
=
{
...
gameData
,
cw_cover
:
(
gameData
as
any
).
cw_cover
||
(
gameData
as
any
).
cover
,
};
gameCardComp
.
init
(
cardData
);
```
### 4) middleLayer 的 Bundle/Scene 加载(平台选择 + 进度保护 + 错误日志)
```
ts
// 平台路径选择(已修复:Android 使用 conf.android.sceneName)
if
(
cc
.
sys
.
isNative
&&
cc
.
sys
.
os
==
cc
.
sys
.
OS_IOS
)
{
sceneName
=
conf
.
ios
.
sceneName
;
version
=
conf
.
ios
.
version
;
bondleUrl
=
`
${
templateBaseUrl
}
/ios/
${
conf
.
ios
.
sceneName
}
`
;
}
else
if
(
cc
.
sys
.
isNative
&&
cc
.
sys
.
os
==
cc
.
sys
.
OS_ANDROID
)
{
sceneName
=
conf
.
android
.
sceneName
;
version
=
conf
.
android
.
version
;
bondleUrl
=
`
${
templateBaseUrl
}
/android/
${
conf
.
android
.
sceneName
}
`
;
// 修复点
}
else
{
sceneName
=
conf
.
android
.
sceneName
;
version
=
''
;
bondleUrl
=
`
${
templateBaseUrl
}
/web_desktop`
;
}
// Bundle 加载与场景运行
cc
.
assetManager
.
loadBundle
(
bondleUrl
,
{
version
},
(
err
,
bundle
)
=>
{
if
(
err
||
!
bundle
)
{
console
.
error
(
'
[Bundle加载失败]
'
,
{
bondleUrl
,
version
,
err
});
this
.
showLog
(
`Bundle加载失败:
${
bondleUrl
}
`
);
callback
&&
callback
(
err
);
return
;
}
this
.
curBundle
=
bundle
;
bundle
.
loadScene
(
sceneName
,
null
,
(
finish
,
total
,
item
)
=>
{
const
safeTotal
=
total
||
1
;
// 防止 total 为 0
const
progress
=
Math
.
floor
((
finish
/
safeTotal
)
*
100
);
if
(
item
&&
(
item
as
any
).
url
)
{
console
.
log
(
'
[场景加载进度]
'
,
{
finish
,
total
:
safeTotal
,
url
:
(
item
as
any
).
url
});
}
this
.
setLoadingProgressBar
(
progress
);
},
(
err
,
scene
)
=>
{
if
(
err
||
!
scene
)
{
console
.
error
(
'
[场景加载失败]
'
,
{
sceneName
,
bondleUrl
,
err
});
this
.
showLog
(
`场景加载失败:
${
sceneName
}
`
);
callback
&&
callback
(
err
);
return
;
}
try
{
cc
.
director
.
runScene
(
scene
,
null
,
()
=>
{
const
middleLayer
=
cc
.
find
(
'
middleLayer
'
);
middleLayer
.
getComponent
(
cc
.
Widget
).
updateAlignment
();
this
.
showCloseGameBtn
();
const
destroyer
=
cc
.
instantiate
(
cc
.
find
(
'
middleLayer/Destroyer
'
));
destroyer
.
parent
=
cc
.
find
(
'
Canvas
'
);
destroyer
.
active
=
true
;
callback
&&
callback
();
});
}
catch
(
e
)
{
console
.
error
(
'
[运行场景异常]
'
,
e
);
this
.
showLog
(
'
运行场景异常
'
);
callback
&&
callback
(
e
);
}
},
);
});
```
### 5) 关闭与退出流程
```
ts
showCloseGameBtn
()
{
const
closeGameBtn
=
cc
.
find
(
'
middleLayer/back_btn
'
);
closeGameBtn
.
active
=
true
;
}
hideCloseGameBtn
()
{
const
closeGameBtn
=
cc
.
find
(
'
middleLayer/back_btn
'
);
closeGameBtn
.
active
=
false
;
}
exitGame
()
{
this
.
onExitGame
();
// 触发资源与状态清理
}
```
### 6) 网络请求示例
```
ts
callNetworkApiGet
(
uri
:
string
,
data
:
any
,
cb
:
Function
)
{
const
xhr
=
new
XMLHttpRequest
();
xhr
.
onreadystatechange
=
()
=>
{
if
(
xhr
.
readyState
===
4
&&
xhr
.
status
>=
200
&&
xhr
.
status
<
400
)
{
cb
(
JSON
.
parse
(
xhr
.
responseText
));
}
};
xhr
.
open
(
'
GET
'
,
`
${
this
.
BASE_URL
}${
uri
}
`
,
true
);
xhr
.
send
();
}
callNetworkApiPost
(
uri
:
string
,
data
:
any
,
cb
:
Function
)
{
const
xhr
=
new
XMLHttpRequest
();
xhr
.
onreadystatechange
=
()
=>
{
if
(
xhr
.
readyState
===
4
&&
xhr
.
status
>=
200
&&
xhr
.
status
<
400
)
{
cb
(
JSON
.
parse
(
xhr
.
responseText
));
}
};
xhr
.
open
(
'
POST
'
,
`
${
this
.
BASE_URL
}${
uri
}
`
,
true
);
xhr
.
setRequestHeader
(
'
Content-Type
'
,
'
application/json
'
);
xhr
.
send
(
JSON
.
stringify
(
data
));
}
```
## 调试与注意事项
-
引擎对象不可直接
`JSON.stringify`
(存在循环引用),调试时输出“安全摘要”(name、uuid、active、parent/children、组件类型)。
-
若进度更新报错(如
`TypeError: Cannot read property '0' of undefined`
),优先检查 bundle 路径与
`config.json`
的
`sceneName`
与目录一致性,使用上面的进度与错误日志定位。
-
命名规则:项目内脚本需以
`_testzg001`
后缀命名,确保发布校验通过。
## 构建与发布
-
通过
`bin/buildCocos.js`
、
`bin/build.js`
执行资源打包与发布。
-
使用
`packages/check-file-name/`
校验脚本命名;必要时用
`packages/replace-uuid/`
与
`packages/引用查找器/`
做资源一致性维护。
\ No newline at end of file
assets/testzg001/script/air_testzg001.js
View file @
0b8505a1
...
...
@@ -3,6 +3,35 @@ const testMockData = {"eof":1,"file":"/storage/emulated/0/Android/data/com.examp
const
recordMockData
=
{
"
text
"
:
"
what can i do for you
"
,
"
audioUrl
"
:
"
https://staging-teach.cdn.ireadabc.com/368ad56174f85e2ff1f39f12bac5c693.mp3
"
};
export
function
initAir
(
_this
)
{
// 安全兜底:确保 _this 存在且具备 log/showTips 方法,避免 e.log 为 null
try
{
if
(
!
_this
)
{
_this
=
{};
}
if
(
typeof
_this
.
log
!==
'
function
'
)
{
_this
.
log
=
(...
args
)
=>
{
try
{
console
.
log
.
apply
(
console
,
args
);
}
catch
(
e
)
{
// 在某些 JSB 环境中 apply 可能异常,使用降级
console
.
log
(
args
&&
args
.
length
===
1
?
args
[
0
]
:
args
.
join
(
'
'
));
}
};
}
if
(
typeof
_this
.
showTips
!==
'
function
'
)
{
_this
.
showTips
=
(
msg
)
=>
{
try
{
console
.
warn
(
msg
);
}
catch
(
e
)
{
// 安全降级
}
};
}
}
catch
(
e
)
{
// 极端情况下保持不抛异常
try
{
console
.
warn
(
'
initAir context fallback failed:
'
,
e
);
}
catch
(
_
)
{}
}
const
realAir
=
{
uploadUrl
:
""
,
uploadData
:
null
,
...
...
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