mirror of
https://github.com/Joker-x-dev/AndroidProject-Compose.git
synced 2025-12-27 15:47:11 +00:00
优化代码以及更新文档说明
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,3 +16,4 @@ local.properties
|
||||
/.idea/
|
||||
/android-project-compose-docs/
|
||||
/context/
|
||||
/blog_post.md
|
||||
|
||||
161
README.md
Normal file
161
README.md
Normal file
@@ -0,0 +1,161 @@
|
||||
<div align="center">
|
||||
|
||||
<img src="docs/images/graphs/logo.svg" width="120" alt="Logo"/>
|
||||
|
||||
# AndroidProject-Compose
|
||||
|
||||
_一个 Android 快速开发框架_
|
||||
|
||||
<!-- 语言切换按钮 -->
|
||||
<div align="center">
|
||||
<a href="README_EN.md">🌍 English</a>
|
||||
</div>
|
||||
|
||||
[](https://github.com/Joker-x-dev/AndroidProject-Compose)
|
||||
[](https://gitee.com/Joker-x-dev/AndroidProject-Compose)
|
||||
[](https://www.pgyer.com/AndroidProject-Compose)
|
||||
[](https://compose.dusksnow.top)
|
||||
[](https://deepwiki.com/Joker-x-dev/AndroidProject-Compose)
|
||||
|
||||
</div>
|
||||
|
||||
## 📖 项目简介
|
||||
|
||||
AndroidProject-Compose 是一个包含网络、状态、导航、主题、数据存储、数据库等基础能力的 **Jetpack Compose 单模块脚手架**,并提供少量功能示例页面,方便你“拉仓库 → 运行 → 填业务”地快速搭建或学习现代 Compose 应用。
|
||||
|
||||
> 如果项目对您有帮助,请给个 Star 支持 ⭐ 这对我来说很重要,能给我带来长期更新维护的动力!
|
||||
|
||||
## 📱 项目预览
|
||||
|
||||
<img src="docs/images/preview/page.png" alt="page"/>
|
||||
|
||||
### 📍 项目地址
|
||||
|
||||
- **GitHub 地址**:[https://github.com/Joker-x-dev/AndroidProject-Compose](https://github.com/Joker-x-dev/AndroidProject-Compose)
|
||||
- **Gitee 地址**:[https://gitee.com/Joker-x-dev/AndroidProject-Compose](https://gitee.com/Joker-x-dev/AndroidProject-Compose)
|
||||
|
||||
> 本脚手架源于青商城的实践,仅保留基础能力与功能示例;完整电商业务与全量 UI/动效/完整业务示例请查看青商城:GitHub https://github.com/Joker-x-dev/CoolMallKotlin | Gitee https://gitee.com/Joker-x-dev/CoolMallKotlin
|
||||
|
||||
### Demo 下载
|
||||
|
||||
**Release 版本(2MB)**:[点击下载体验](https://www.pgyer.com/AndroidProject-Compose)
|
||||
- **支持系统**:Android 6.0 及以上
|
||||
- **更新说明**:预览版本会不定时更新,可能不会完全同步最新的代码变更
|
||||
|
||||
### 说明文档
|
||||
|
||||
- **说明文档**:[在线查看](https://compose.dusksnow.top)
|
||||
- **说明**:与代码同步的在线文档,包含快速开始、架构说明、示例路由、常见定制点等,便于理解项目与学习。
|
||||
|
||||
## 🛠️ 技术栈
|
||||
|
||||
### 核心技术
|
||||
|
||||
| 类别 | 技术选型 | 版本号 | 说明 |
|
||||
|-------|---------------------------|------------|-------------------|
|
||||
| 编程语言 | Kotlin | 2.2.21 | 100% Kotlin 开发 |
|
||||
| UI 框架 | Jetpack Compose | 2025.11.01 | 声明式 UI 框架 |
|
||||
| 依赖注入 | Hilt | 2.57.2 | 基于 Dagger 的依赖注入框架 |
|
||||
|
||||
### 功能模块
|
||||
|
||||
| 类别 | 技术选型 | 版本号 | 说明 |
|
||||
|-------|-----------------------|---------------|------------------|
|
||||
| 导航 | Navigation Compose | 2.9.6 | Compose 导航组件 |
|
||||
| 网络请求 | Retrofit + OkHttp | 3.0.0 + 5.3.2 | HTTP 客户端 |
|
||||
|
||||
### 数据存储
|
||||
|
||||
| 类别 | 技术选型 | 版本号 | 说明 |
|
||||
|------|------|-------|------------|
|
||||
| 数据库 | Room | 2.8.4 | SQLite 数据库 |
|
||||
| 本地存储 | MMKV | 2.2.4 | 高性能键值存储 |
|
||||
|
||||
### 开发工具
|
||||
|
||||
| 类别 | 技术选型 | 版本号 | 说明 |
|
||||
|------|---------------|--------|-------------|
|
||||
| 日志框架 | Timber | 5.0.1 | 日志管理 |
|
||||
| 网络调试 | Chucker | 4.2.0 | 网络请求监控 |
|
||||
| 内存检测 | LeakCanary | 2.14 | 内存泄漏检测 |
|
||||
|
||||
## 📱 功能模块目录
|
||||
|
||||
- **主模块 (main)**
|
||||
- 主页面 (main)
|
||||
- 基础能力示例 (core-demo)
|
||||
- 导航示例 (navigation-demo)
|
||||
|
||||
|
||||
- **认证模块 (auth)**
|
||||
- 登录页 (login)
|
||||
|
||||
|
||||
- **用户模块 (user)**
|
||||
- 用户信息 (info)
|
||||
|
||||
|
||||
- **示例模块 (demo)**
|
||||
- 通用网络请求示例 (network-demo)
|
||||
- 通用分页列表示例 (network-list-demo)
|
||||
- 数据库示例 (database)
|
||||
- 本地存储示例 (local-storage)
|
||||
- 状态管理示例 (state-management)
|
||||
- 网络请求示例 (network-request)
|
||||
- 带参跳转示例 (navigation-with-args)
|
||||
- 结果回传示例 (navigation-result)
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
├── app/ # 应用入口
|
||||
├── core/ # 核心
|
||||
│ ├── base/ # 基础抽象
|
||||
│ ├── data/ # 数据层
|
||||
│ ├── database/ # 数据库
|
||||
│ ├── datastore/ # 数据存储
|
||||
│ ├── designsystem/ # 设计系统
|
||||
│ ├── model/ # 数据模型
|
||||
│ ├── network/ # 网络层
|
||||
│ ├── result/ # 结果处理
|
||||
│ ├── state/ # 状态管理
|
||||
│ ├── ui/ # UI 组件
|
||||
│ └── util/ # 工具类
|
||||
├── navigation/ # 导航模块
|
||||
│ ├── routes/ # 路由定义
|
||||
│ ├── results/ # 路由返回结果
|
||||
│ └── extension/ # 导航扩展
|
||||
├── feature/ # 功能模块
|
||||
│ ├── main/ # 主模块
|
||||
│ ├── auth/ # 认证模块
|
||||
│ ├── user/ # 用户模块
|
||||
│ └── demo/ # 示例模块
|
||||
└── MainActivityViewModel.kt # 宿主级共享 ViewModel
|
||||
```
|
||||
|
||||
## 👥 加入群聊
|
||||
|
||||
欢迎加入开发者交流群,一起分享学习心得,讨论技术问题!
|
||||
|
||||
<div align="left">
|
||||
<img src="docs/images/group/qq.jpg" width="200" alt="QQ群二维码"/>
|
||||
<p>扫码或搜索群号加入 QQ 群</p>
|
||||
</div>
|
||||
|
||||
## 🤝 参与贡献
|
||||
|
||||
这是一个开放的学习项目,欢迎所有对 Android 开发感兴趣的开发者参与贡献!
|
||||
|
||||
### 🎯 贡献方式
|
||||
|
||||
- **代码贡献**: 提交 Pull Request,完善功能实现或修复问题
|
||||
- **问题反馈**: 通过 Issue 报告 Bug 或提出功能建议
|
||||
- **文档优化**: 完善项目文档、添加使用说明或开发指南
|
||||
- **设计支持**: 提供 UI/UX 设计建议或素材资源
|
||||
- **测试协助**: 参与功能测试,提供使用反馈和改进建议
|
||||
|
||||
### 📋 贡献指南
|
||||
|
||||
- 提交代码前请确保遵循项目的编码规范
|
||||
- 新功能开发建议先创建 Issue 讨论可行性
|
||||
- 欢迎分享学习心得和技术总结
|
||||
158
README_EN.md
Normal file
158
README_EN.md
Normal file
@@ -0,0 +1,158 @@
|
||||
<div align="center">
|
||||
|
||||
<img src="docs/images/graphs/logo.svg" width="120" alt="Logo"/>
|
||||
|
||||
# AndroidProject-Compose
|
||||
|
||||
_A fast-start Android framework built with Jetpack Compose_
|
||||
|
||||
<!-- Language Switch Button -->
|
||||
<div align="center">
|
||||
<a href="README.md">🌍 中文</a>
|
||||
</div>
|
||||
|
||||
[](https://github.com/Joker-x-dev/AndroidProject-Compose)
|
||||
[](https://gitee.com/Joker-x-dev/AndroidProject-Compose)
|
||||
[](https://www.pgyer.com/AndroidProject-Compose)
|
||||
[](https://compose.dusksnow.top)
|
||||
[](https://deepwiki.com/Joker-x-dev/AndroidProject-Compose)
|
||||
|
||||
</div>
|
||||
|
||||
## 📖 Project Overview
|
||||
|
||||
AndroidProject-Compose is a **single-module Jetpack Compose scaffold** that ships with the essential building blocks for networking, state, navigation, theming, data storage, and database access. It also includes a few feature demo pages so you can “clone → run → plug in your business logic” to quickly build or learn a modern Compose app.
|
||||
|
||||
> If this project helps you, please give it a Star ⭐ It means a lot and keeps me motivated to maintain and update the project long-term!
|
||||
|
||||
## 📱 Preview
|
||||
|
||||
<img src="docs/images/preview/page.png" alt="page"/>
|
||||
|
||||
### 📍 Project Links
|
||||
|
||||
- **GitHub**: [https://github.com/Joker-x-dev/AndroidProject-Compose](https://github.com/Joker-x-dev/AndroidProject-Compose)
|
||||
- **Gitee**: [https://gitee.com/Joker-x-dev/AndroidProject-Compose](https://gitee.com/Joker-x-dev/AndroidProject-Compose)
|
||||
|
||||
> This scaffold originates from the CoolMall practice project and keeps only the foundational capabilities plus sample pages. For the full e-commerce business, complete UI/animations, and full-featured demos, see CoolMall: GitHub https://github.com/Joker-x-dev/CoolMallKotlin | Gitee https://gitee.com/Joker-x-dev/CoolMallKotlin
|
||||
|
||||
### Demo Download
|
||||
|
||||
**Release build (2MB)**: [Download](https://www.pgyer.com/AndroidProject-Compose)
|
||||
- **Supported OS**: Android 6.0 and above
|
||||
- **Release notes**: Preview builds update occasionally and may not always reflect the latest code changes
|
||||
|
||||
### Documentation
|
||||
|
||||
- **Docs**: [View online](https://compose.dusksnow.top)
|
||||
- **Note**: Online docs stay in sync with the code and cover quick start, architecture, sample routes, common customization points, and more.
|
||||
|
||||
## 🛠️ Tech Stack
|
||||
|
||||
### Core Technologies
|
||||
|
||||
| Category | Technology | Version | Description |
|
||||
|-----------------------|---------------------|------------|------------------------------|
|
||||
| Programming Language | Kotlin | 2.2.21 | 100% Kotlin |
|
||||
| UI Framework | Jetpack Compose | 2025.11.01 | Declarative UI framework |
|
||||
| Dependency Injection | Hilt | 2.57.2 | Dagger-based DI framework |
|
||||
|
||||
### Feature Modules
|
||||
|
||||
| Category | Technology | Version | Description |
|
||||
|------------|------------------------|---------------|---------------------------|
|
||||
| Navigation | Navigation Compose | 2.9.6 | Compose navigation |
|
||||
| Network | Retrofit + OkHttp | 3.0.0 + 5.3.2 | HTTP client |
|
||||
|
||||
### Data Storage
|
||||
|
||||
| Category | Technology | Version | Description |
|
||||
|---------------|------------|---------|----------------------------------|
|
||||
| Database | Room | 2.8.4 | SQLite database |
|
||||
| Local Storage | MMKV | 2.2.4 | High-performance key-value store |
|
||||
|
||||
### Development Tools
|
||||
|
||||
| Category | Technology | Version | Description |
|
||||
|-------------------|------------|---------|------------------------|
|
||||
| Logging | Timber | 5.0.1 | Log management |
|
||||
| Network Debugging | Chucker | 4.2.0 | Network request monitor|
|
||||
| Memory Leak Check | LeakCanary | 2.14 | Memory leak detection |
|
||||
|
||||
## 📱 Feature Module Directory
|
||||
|
||||
- **Main Module (main)**
|
||||
- Main page (main)
|
||||
- Core capability demos (core-demo)
|
||||
- Navigation demos (navigation-demo)
|
||||
|
||||
- **Auth Module (auth)**
|
||||
- Login (login)
|
||||
|
||||
- **User Module (user)**
|
||||
- User info (info)
|
||||
|
||||
- **Demo Module (demo)**
|
||||
- Generic network request demo (network-demo)
|
||||
- Generic paged list demo (network-list-demo)
|
||||
- Database demo (database)
|
||||
- Local storage demo (local-storage)
|
||||
- State management demo (state-management)
|
||||
- Network request demo (network-request)
|
||||
- Navigation with args (navigation-with-args)
|
||||
- Navigation result passing (navigation-result)
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
├── app/ # App entry
|
||||
├── core/ # Core
|
||||
│ ├── base/ # Base abstractions
|
||||
│ ├── data/ # Data layer
|
||||
│ ├── database/ # Database
|
||||
│ ├── datastore/ # Data storage
|
||||
│ ├── designsystem/ # Design system
|
||||
│ ├── model/ # Data models
|
||||
│ ├── network/ # Network layer
|
||||
│ ├── result/ # Result handling
|
||||
│ ├── state/ # State management
|
||||
│ ├── ui/ # UI components
|
||||
│ └── util/ # Utilities
|
||||
├── navigation/ # Navigation module
|
||||
│ ├── routes/ # Route definitions
|
||||
│ ├── results/ # Route results
|
||||
│ └── extension/ # Navigation extensions
|
||||
├── feature/ # Feature modules
|
||||
│ ├── main/ # Main module
|
||||
│ ├── auth/ # Auth module
|
||||
│ ├── user/ # User module
|
||||
│ └── demo/ # Demo module
|
||||
└── MainActivityViewModel.kt # Host-level shared ViewModel
|
||||
```
|
||||
|
||||
## 👥 Join the Community
|
||||
|
||||
Welcome to the developer group—share learning notes and discuss technical questions together!
|
||||
|
||||
<div align="left">
|
||||
<img src="docs/images/group/qq.jpg" width="200" alt="QQ group QR code"/>
|
||||
<p>Scan or search the group number to join the QQ group</p>
|
||||
</div>
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
This is an open learning project. All Android enthusiasts are welcome to contribute!
|
||||
|
||||
### 🎯 How to Contribute
|
||||
|
||||
- **Code Contributions**: Submit pull requests to improve features or fix issues
|
||||
- **Issue Feedback**: Report bugs or suggest features via Issues
|
||||
- **Documentation**: Enhance docs, add usage guides or developer guides
|
||||
- **Design Support**: Provide UI/UX suggestions or assets
|
||||
- **Testing Help**: Join feature testing and share feedback
|
||||
|
||||
### 📋 Contribution Guidelines
|
||||
|
||||
- Please follow the project coding conventions before submitting code
|
||||
- For new features, create an Issue first to discuss feasibility
|
||||
- Sharing learning notes and technical takeaways is encouraged
|
||||
15
app/proguard-rules.pro
vendored
15
app/proguard-rules.pro
vendored
@@ -20,8 +20,13 @@
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
# toast 混淆规则
|
||||
-keep class com.hjq.toast.** {*;}
|
||||
|
||||
# xxp权限混淆规则
|
||||
-keep class com.hjq.permissions.** { *; }
|
||||
# xxp权限混淆规则 地址: https://github.com/getActivity/XXPermissions/blob/master/library/proguard-permissions.pro
|
||||
-keepclassmembers interface com.hjq.permissions.start.IStartActivityDelegate {
|
||||
<methods>;
|
||||
}
|
||||
-keepclassmembers interface com.hjq.permissions.fragment.IFragmentMethodNative {
|
||||
<methods>;
|
||||
}
|
||||
-keepclassmembers class androidx.fragment.app.Fragment {
|
||||
androidx.fragment.app.FragmentActivity getActivity();
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.joker.kit.core.model.entity
|
||||
|
||||
import androidx.annotation.Keep
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
@@ -18,6 +20,7 @@ import kotlinx.serialization.Serializable
|
||||
* @param updateTime 更新时间
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Keep
|
||||
@Serializable
|
||||
data class User(
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.joker.kit.core.model.network
|
||||
|
||||
import androidx.annotation.Keep
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
@@ -11,6 +13,7 @@ import kotlinx.serialization.Serializable
|
||||
* @param message 出错的提示信息
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Keep
|
||||
@Serializable
|
||||
data class NetworkResponse<T>(
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.joker.kit.core.network.service
|
||||
|
||||
import androidx.annotation.Keep
|
||||
|
||||
import com.joker.kit.core.model.entity.User
|
||||
import com.joker.kit.core.model.network.NetworkResponse
|
||||
import retrofit2.http.GET
|
||||
@@ -9,6 +11,7 @@ import retrofit2.http.GET
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Keep
|
||||
interface UserInfoService {
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,12 +23,17 @@ class DemoCounterState @Inject constructor(
|
||||
|
||||
/**
|
||||
* 计数器值
|
||||
*
|
||||
* @return 计数器 StateFlow
|
||||
* @author Joker.X
|
||||
*/
|
||||
private val _count = MutableStateFlow(0)
|
||||
val count: StateFlow<Int> = _count.asStateFlow()
|
||||
|
||||
/**
|
||||
* +1
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun increase() {
|
||||
appScope.launch {
|
||||
@@ -38,6 +43,8 @@ class DemoCounterState @Inject constructor(
|
||||
|
||||
/**
|
||||
* -1,最低为 0
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun decrease() {
|
||||
appScope.launch {
|
||||
@@ -47,6 +54,8 @@ class DemoCounterState @Inject constructor(
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun reset() {
|
||||
appScope.launch {
|
||||
|
||||
@@ -182,4 +182,4 @@ class UserState @Inject constructor(
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* 应用状态模块,提供应用级协程作用域
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@@ -20,6 +22,9 @@ object AppStateModule {
|
||||
/**
|
||||
* 提供应用级别的协程作用域
|
||||
* SupervisorJob 确保子协程失败不会终止整个作用域
|
||||
*
|
||||
* @return 应用级 CoroutineScope
|
||||
* @author Joker.X
|
||||
*/
|
||||
@ApplicationScope
|
||||
@Singleton
|
||||
@@ -31,6 +36,8 @@ object AppStateModule {
|
||||
|
||||
/**
|
||||
* 应用级协程作用域限定符
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Qualifier
|
||||
|
||||
@@ -30,6 +30,8 @@ class LoginViewModel @Inject constructor(
|
||||
/**
|
||||
* 模拟登录:构造假的 Auth/User,写入 UserState,演示路由拦截放行。
|
||||
* 真实项目中,这里会是网络请求,登录成功后会有 token 等信息返回。
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun login() {
|
||||
viewModelScope.launch {
|
||||
@@ -52,6 +54,8 @@ class LoginViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 模拟退出登录,清空全局 UserState
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun logout() {
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.joker.kit.navigation.routes.DemoRoutes
|
||||
|
||||
/**
|
||||
* 数据库示例页面导航
|
||||
*
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.databaseScreen(sharedTransitionScope: SharedTransitionScope) {
|
||||
|
||||
@@ -7,6 +7,10 @@ import androidx.navigation.NavHostController
|
||||
|
||||
/**
|
||||
* Demo 模块导航图
|
||||
*
|
||||
* @param navController 导航控制器
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.demoGraph(
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.joker.kit.navigation.routes.DemoRoutes
|
||||
|
||||
/**
|
||||
* 本地存储示例页面导航
|
||||
*
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.localStorageScreen(sharedTransitionScope: SharedTransitionScope) {
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.joker.kit.navigation.routes.DemoRoutes
|
||||
|
||||
/**
|
||||
* 结果回传示例页面导航
|
||||
*
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.navigationResultScreen(sharedTransitionScope: SharedTransitionScope) {
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.joker.kit.navigation.routes.DemoRoutes
|
||||
|
||||
/**
|
||||
* 带参跳转示例页面导航
|
||||
*
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.navigationWithArgsScreen(sharedTransitionScope: SharedTransitionScope) {
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.joker.kit.navigation.routes.DemoRoutes
|
||||
|
||||
/**
|
||||
* Network Demo 页面导航
|
||||
*
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.networkDemoScreen(sharedTransitionScope: SharedTransitionScope) {
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.joker.kit.navigation.routes.DemoRoutes
|
||||
|
||||
/**
|
||||
* Network List Demo 页面导航
|
||||
*
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.networkListDemoScreen(sharedTransitionScope: SharedTransitionScope) {
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.joker.kit.navigation.routes.DemoRoutes
|
||||
|
||||
/**
|
||||
* 网络请求示例页面导航
|
||||
*
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.networkRequestScreen(sharedTransitionScope: SharedTransitionScope) {
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.joker.kit.navigation.routes.DemoRoutes
|
||||
|
||||
/**
|
||||
* 状态管理示例页面导航
|
||||
*
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
fun NavGraphBuilder.stateManagementScreen(sharedTransitionScope: SharedTransitionScope) {
|
||||
|
||||
@@ -53,6 +53,7 @@ import java.util.Locale
|
||||
* 数据库示例路由
|
||||
*
|
||||
* @param viewModel Hilt 注入的 DatabaseViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun DatabaseRoute(
|
||||
@@ -90,6 +91,7 @@ internal fun DatabaseRoute(
|
||||
* @param onDeleteItem 删除指定记录
|
||||
* @param onClearAll 清空所有记录
|
||||
* @param onBackClick 返回按钮回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -132,6 +134,7 @@ internal fun DatabaseScreen(
|
||||
* @param onAddClick 新增记录回调
|
||||
* @param onDeleteItem 删除记录回调
|
||||
* @param onClearAll 清空列表回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun DatabaseContent(
|
||||
@@ -177,6 +180,7 @@ private fun DatabaseContent(
|
||||
* @param onAddClick 新增记录
|
||||
* @param onClearAll 清空全部
|
||||
* @param canClear 是否允许清空按钮启用
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun InputCard(
|
||||
@@ -249,6 +253,7 @@ private fun InputCard(
|
||||
*
|
||||
* @param items Demo 数据列表
|
||||
* @param onDeleteItem 删除单条记录回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun DemoListCard(
|
||||
@@ -298,6 +303,7 @@ private fun DemoListCard(
|
||||
*
|
||||
* @param item Demo 实体
|
||||
* @param onDeleteItem 删除该条记录回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun DemoListItem(
|
||||
@@ -337,6 +343,8 @@ private fun DemoListItem(
|
||||
|
||||
/**
|
||||
* 数据库界面浅色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -352,6 +360,8 @@ private fun DatabasePreview() {
|
||||
|
||||
/**
|
||||
* 数据库界面深色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -367,6 +377,9 @@ private fun DatabasePreviewDark() {
|
||||
|
||||
/**
|
||||
* 预览用 Demo 数据
|
||||
*
|
||||
* @return 示例数据列表
|
||||
* @author Joker.X
|
||||
*/
|
||||
private fun previewDemoItems() = listOf(
|
||||
DemoEntity(id = 1, title = "演示标题 A", description = "这是第一条记录"),
|
||||
|
||||
@@ -42,6 +42,7 @@ import com.joker.kit.feature.demo.viewmodel.LocalStorageViewModel
|
||||
* 本地存储示例路由
|
||||
*
|
||||
* @param viewModel Hilt 注入的 LocalStorageViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun LocalStorageRoute(
|
||||
@@ -85,6 +86,7 @@ internal fun LocalStorageRoute(
|
||||
* @param onClearUser 清除用户信息
|
||||
* @param onReloadUser 重新读取用户信息
|
||||
* @param onBackClick 返回按钮回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -104,7 +106,6 @@ internal fun LocalStorageScreen(
|
||||
AppScaffold(
|
||||
titleText = "本地存储",
|
||||
onBackClick = onBackClick,
|
||||
contentShouldConsumePadding = true
|
||||
) {
|
||||
LocalStorageContent(
|
||||
userId = userId,
|
||||
@@ -134,6 +135,7 @@ internal fun LocalStorageScreen(
|
||||
* @param onSaveUser 保存用户
|
||||
* @param onClearUser 清除用户
|
||||
* @param onReloadUser 重新读取用户
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun LocalStorageContent(
|
||||
@@ -183,6 +185,7 @@ private fun LocalStorageContent(
|
||||
* @param onSaveUser 保存用户
|
||||
* @param onClearUser 清除用户
|
||||
* @param onReloadUser 重新读取用户
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun UserCard(
|
||||
@@ -269,6 +272,8 @@ private fun UserCard(
|
||||
|
||||
/**
|
||||
* 本地存储界面浅色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -285,6 +290,8 @@ private fun LocalStoragePreview() {
|
||||
|
||||
/**
|
||||
* 本地存储界面深色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
|
||||
@@ -17,6 +17,9 @@ import com.joker.kit.feature.demo.viewmodel.NavigationResultViewModel
|
||||
|
||||
/**
|
||||
* 结果回传示例路由
|
||||
*
|
||||
* @param viewModel Hilt 注入的 NavigationResultViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun NavigationResultRoute(
|
||||
@@ -31,7 +34,9 @@ internal fun NavigationResultRoute(
|
||||
/**
|
||||
* 结果回传示例界面
|
||||
*
|
||||
* @param onSendResult 发送结果并返回回调
|
||||
* @param onBackClick 返回按钮回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -49,6 +54,9 @@ internal fun NavigationResultScreen(
|
||||
|
||||
/**
|
||||
* 结果回传内容视图
|
||||
*
|
||||
* @param onSendResult 发送结果回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun NavigationResultContent(onSendResult: () -> Unit) {
|
||||
@@ -64,6 +72,8 @@ private fun NavigationResultContent(onSendResult: () -> Unit) {
|
||||
|
||||
/**
|
||||
* 结果回传界面浅色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -75,6 +85,8 @@ private fun NavigationResultPreview() {
|
||||
|
||||
/**
|
||||
* 结果回传界面深色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
|
||||
@@ -11,6 +11,9 @@ import com.joker.kit.feature.demo.viewmodel.NavigationWithArgsViewModel
|
||||
|
||||
/**
|
||||
* 带参跳转示例路由
|
||||
*
|
||||
* @param viewModel Hilt 注入的 NavigationWithArgsViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun NavigationWithArgsRoute(
|
||||
@@ -25,7 +28,9 @@ internal fun NavigationWithArgsRoute(
|
||||
/**
|
||||
* 带参跳转示例界面
|
||||
*
|
||||
* @param goodsId 传入的商品 ID
|
||||
* @param onBackClick 返回按钮回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -43,6 +48,9 @@ internal fun NavigationWithArgsScreen(
|
||||
|
||||
/**
|
||||
* 带参跳转内容视图
|
||||
*
|
||||
* @param goodsId 传入的商品 ID
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun NavigationWithArgsContent(goodsId: Long) {
|
||||
@@ -51,6 +59,8 @@ private fun NavigationWithArgsContent(goodsId: Long) {
|
||||
|
||||
/**
|
||||
* 带参跳转界面浅色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -62,6 +72,8 @@ private fun NavigationWithArgsPreview() {
|
||||
|
||||
/**
|
||||
* 带参跳转界面深色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
|
||||
@@ -20,6 +20,9 @@ import com.joker.kit.feature.demo.viewmodel.NetworkDemoViewModel
|
||||
|
||||
/**
|
||||
* Network Demo 路由
|
||||
*
|
||||
* @param viewModel Hilt 注入的 NetworkDemoViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun NetworkDemoRoute(
|
||||
@@ -41,6 +44,7 @@ internal fun NetworkDemoRoute(
|
||||
* @param uiState UI 状态
|
||||
* @param onBackClick 返回按钮回调
|
||||
* @param onRetry 重试回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -66,6 +70,7 @@ internal fun NetworkDemoScreen(
|
||||
* Network Demo 内容视图
|
||||
*
|
||||
* @param data 商品数据
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun NetworkDemoContent(data: Goods) {
|
||||
@@ -79,6 +84,8 @@ private fun NetworkDemoContent(data: Goods) {
|
||||
|
||||
/**
|
||||
* Network Demo 界面浅色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -90,6 +97,8 @@ private fun NetworkDemoPreview() {
|
||||
|
||||
/**
|
||||
* Network Demo 界面深色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -101,6 +110,9 @@ private fun NetworkDemoPreviewDark() {
|
||||
|
||||
/**
|
||||
* 模拟商品数据
|
||||
*
|
||||
* @return 示例商品
|
||||
* @author Joker.X
|
||||
*/
|
||||
private fun mockGoods() = Goods(
|
||||
id = 1,
|
||||
|
||||
@@ -23,6 +23,9 @@ import com.joker.kit.feature.demo.viewmodel.NetworkListDemoViewModel
|
||||
|
||||
/**
|
||||
* Network List Demo 路由
|
||||
*
|
||||
* @param viewModel Hilt 注入的 NetworkListDemoViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun NetworkListDemoRoute(
|
||||
@@ -62,6 +65,7 @@ internal fun NetworkListDemoRoute(
|
||||
* @param shouldTriggerLoadMore 是否触发加载更多
|
||||
* @param onBackClick 返回回调
|
||||
* @param onRetry 重试回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -105,6 +109,7 @@ internal fun NetworkListDemoScreen(
|
||||
* @param onRefresh 刷新回调
|
||||
* @param onLoadMore 加载更多回调
|
||||
* @param shouldTriggerLoadMore 是否触发加载更多
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -131,6 +136,9 @@ private fun NetworkListDemoContent(
|
||||
|
||||
/**
|
||||
* 简单展示商品信息的列表项
|
||||
*
|
||||
* @param goods 商品实体
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun GoodsListItem(goods: Goods) {
|
||||
@@ -146,6 +154,8 @@ private fun GoodsListItem(goods: Goods) {
|
||||
|
||||
/**
|
||||
* Network List Demo 界面浅色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -161,6 +171,8 @@ private fun NetworkListDemoPreview() {
|
||||
|
||||
/**
|
||||
* Network List Demo 界面深色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -176,6 +188,9 @@ private fun NetworkListDemoPreviewDark() {
|
||||
|
||||
/**
|
||||
* 预览用商品列表数据
|
||||
*
|
||||
* @return 商品预览数据列表
|
||||
* @author Joker.X
|
||||
*/
|
||||
private fun previewGoodsList() = listOf(
|
||||
Goods(id = 1, title = "小米手机 14", subTitle = "直屏旗舰", price = 3999, sold = 5000),
|
||||
|
||||
@@ -24,6 +24,9 @@ import com.joker.kit.feature.demo.viewmodel.NetworkRequestViewModel
|
||||
|
||||
/**
|
||||
* 网络请求示例路由
|
||||
*
|
||||
* @param viewModel Hilt 注入的 NetworkRequestViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun NetworkRequestRoute(
|
||||
@@ -45,6 +48,7 @@ internal fun NetworkRequestRoute(
|
||||
* @param goods 商品信息
|
||||
* @param onBackClick 返回按钮回调
|
||||
* @param onRequestClick 请求按钮回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -69,6 +73,7 @@ internal fun NetworkRequestScreen(
|
||||
*
|
||||
* @param goods 商品信息
|
||||
* @param onRequestClick 请求按钮回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun NetworkRequestContent(
|
||||
@@ -99,6 +104,7 @@ private fun NetworkRequestContent(
|
||||
* 网络请求结果卡片视图
|
||||
*
|
||||
* @param goods 商品信息
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun CardResult(goods: Goods) {
|
||||
@@ -116,6 +122,9 @@ private fun CardResult(goods: Goods) {
|
||||
|
||||
/**
|
||||
* 模拟商品信息
|
||||
*
|
||||
* @return 示例商品
|
||||
* @author Joker.X
|
||||
*/
|
||||
private fun mockGoods() = Goods(
|
||||
id = 1,
|
||||
@@ -128,6 +137,8 @@ private fun mockGoods() = Goods(
|
||||
|
||||
/**
|
||||
* 网络请求界面浅色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -141,6 +152,8 @@ private fun NetworkRequestPreview() {
|
||||
|
||||
/**
|
||||
* 网络请求界面深色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -150,4 +163,4 @@ private fun NetworkRequestPreviewDark() {
|
||||
goods = mockGoods(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.joker.kit.feature.demo.viewmodel.StateManagementViewModel
|
||||
* 状态管理示例路由
|
||||
*
|
||||
* @param viewModel Hilt 注入的 StateManagementViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun StateManagementRoute(
|
||||
@@ -62,6 +63,7 @@ internal fun StateManagementRoute(
|
||||
* @param onDecrease -1 回调
|
||||
* @param onReset 重置回调
|
||||
* @param onBackClick 返回按钮回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -92,6 +94,7 @@ internal fun StateManagementScreen(
|
||||
* @param onIncrease 递增回调
|
||||
* @param onDecrease 递减回调
|
||||
* @param onReset 重置回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun StateManagementContent(
|
||||
@@ -116,6 +119,11 @@ private fun StateManagementContent(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态管理介绍卡片
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun IntroCard() {
|
||||
Card(
|
||||
@@ -147,6 +155,7 @@ private fun IntroCard() {
|
||||
* @param onIncrease 递增回调
|
||||
* @param onDecrease 递减回调
|
||||
* @param onReset 重置回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun CounterCard(
|
||||
@@ -203,6 +212,8 @@ private fun CounterCard(
|
||||
|
||||
/**
|
||||
* 状态管理界面浅色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -214,6 +225,8 @@ private fun StateManagementPreview() {
|
||||
|
||||
/**
|
||||
* 状态管理界面深色主题预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
|
||||
@@ -21,6 +21,7 @@ import javax.inject.Inject
|
||||
* @param navigator 导航管理器
|
||||
* @param userState 用户状态管理
|
||||
* @param demoRepository Demo 仓库,封装 DemoDataSource 的增删改查
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class DatabaseViewModel @Inject constructor(
|
||||
@@ -40,6 +41,9 @@ class DatabaseViewModel @Inject constructor(
|
||||
/**
|
||||
* Demo 表数据流
|
||||
* UI 侧直接 collectAsState() 获取最新列表
|
||||
*
|
||||
* @return Demo 列表状态流
|
||||
* @author Joker.X
|
||||
*/
|
||||
val items: StateFlow<List<DemoEntity>> = demoRepository
|
||||
.observeItems()
|
||||
@@ -53,6 +57,7 @@ class DatabaseViewModel @Inject constructor(
|
||||
* 更新标题输入
|
||||
*
|
||||
* @param value 文本框中的标题
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onTitleChange(value: String) {
|
||||
_title.value = value
|
||||
@@ -62,6 +67,7 @@ class DatabaseViewModel @Inject constructor(
|
||||
* 更新描述输入
|
||||
*
|
||||
* @param value 文本框中的描述
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onDescriptionChange(value: String) {
|
||||
_description.value = value
|
||||
@@ -69,6 +75,8 @@ class DatabaseViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 新增一条记录(仅当标题非空)
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun addItem() {
|
||||
val title = _title.value.trim()
|
||||
@@ -88,6 +96,7 @@ class DatabaseViewModel @Inject constructor(
|
||||
* 删除指定记录
|
||||
*
|
||||
* @param id 记录主键
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun deleteItem(id: Long) {
|
||||
viewModelScope.launch {
|
||||
@@ -97,6 +106,8 @@ class DatabaseViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 清空全部记录
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun clearAll() {
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -21,6 +21,7 @@ import kotlinx.coroutines.launch
|
||||
* @param navigator 导航管理器
|
||||
* @param userState 用户状态管理
|
||||
* @param userInfoStoreRepository 用户信息本地存储仓库
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class LocalStorageViewModel @Inject constructor(
|
||||
@@ -53,6 +54,7 @@ class LocalStorageViewModel @Inject constructor(
|
||||
* 用户 id 文本更新
|
||||
*
|
||||
* @param value 输入的 id 字符串
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onUserIdChange(value: String) {
|
||||
_userId.value = value
|
||||
@@ -62,6 +64,7 @@ class LocalStorageViewModel @Inject constructor(
|
||||
* 用户昵称输入更新
|
||||
*
|
||||
* @param value 昵称文本
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onNickNameChange(value: String) {
|
||||
_nickName.value = value
|
||||
@@ -71,6 +74,7 @@ class LocalStorageViewModel @Inject constructor(
|
||||
* 头像链接输入更新
|
||||
*
|
||||
* @param value 头像 URL
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onAvatarChange(value: String) {
|
||||
_avatar.value = value
|
||||
@@ -78,6 +82,8 @@ class LocalStorageViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 保存用户信息到本地
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun saveUser() {
|
||||
viewModelScope.launch {
|
||||
@@ -95,6 +101,8 @@ class LocalStorageViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 清除本地用户信息
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun clearUser() {
|
||||
viewModelScope.launch {
|
||||
@@ -108,6 +116,8 @@ class LocalStorageViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 重新读取用户信息
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun loadUser() {
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -10,6 +10,10 @@ import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 结果回传示例页 ViewModel
|
||||
*
|
||||
* @param navigator 导航管理器
|
||||
* @param userState 用户状态
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class NavigationResultViewModel @Inject constructor(
|
||||
@@ -19,6 +23,11 @@ class NavigationResultViewModel @Inject constructor(
|
||||
navigator = navigator,
|
||||
userState = userState
|
||||
) {
|
||||
/**
|
||||
* 回传结果并返回上一页
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun sendResultAndBack() {
|
||||
popBackStackWithResult(
|
||||
DemoResultKey,
|
||||
|
||||
@@ -11,6 +11,11 @@ import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 带参跳转示例页 ViewModel
|
||||
*
|
||||
* @param navigator 导航管理器
|
||||
* @param userState 用户状态
|
||||
* @param savedStateHandle 路由参数存储
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class NavigationWithArgsViewModel @Inject constructor(
|
||||
@@ -23,11 +28,17 @@ class NavigationWithArgsViewModel @Inject constructor(
|
||||
) {
|
||||
/**
|
||||
* 路由参数
|
||||
* */
|
||||
*
|
||||
* @return 路由解析结果
|
||||
* @author Joker.X
|
||||
*/
|
||||
private val route = savedStateHandle.toRoute<DemoRoutes.NavigationWithArgs>()
|
||||
|
||||
/**
|
||||
* 商品ID
|
||||
* */
|
||||
*
|
||||
* @return 传递的商品 ID
|
||||
* @author Joker.X
|
||||
*/
|
||||
val goodsId: Long = route.goodsId
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.inject.Inject
|
||||
* @param navigator 导航管理器
|
||||
* @param userState 用户状态管理
|
||||
* @param goodsRepository 商品数据仓库
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class NetworkDemoViewModel @Inject constructor(
|
||||
@@ -30,8 +31,11 @@ class NetworkDemoViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 重写请求API Flow,获取商品信息
|
||||
*
|
||||
* @return 商品信息响应流
|
||||
* @author Joker.X
|
||||
*/
|
||||
override fun requestApiFlow(): Flow<NetworkResponse<Goods>> {
|
||||
return goodsRepository.getGoodsInfo("1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import javax.inject.Inject
|
||||
* @param navigator 导航器
|
||||
* @param userState 用户状态管理
|
||||
* @param goodsRepository 商品数据仓库
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class NetworkListDemoViewModel @Inject constructor(
|
||||
@@ -35,6 +36,9 @@ class NetworkListDemoViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 重写请求API Flow,获取商品列表
|
||||
*
|
||||
* @return 商品分页数据流
|
||||
* @author Joker.X
|
||||
*/
|
||||
override fun requestListData(): Flow<NetworkResponse<NetworkPageData<Goods>>> {
|
||||
return goodsRepository.getGoodsPage(
|
||||
|
||||
@@ -16,6 +16,11 @@ import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 网络请求示例页 ViewModel
|
||||
*
|
||||
* @param navigator 导航管理器
|
||||
* @param userState 用户状态
|
||||
* @param goodsRepository 商品仓库
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class NetworkRequestViewModel @Inject constructor(
|
||||
@@ -29,12 +34,17 @@ class NetworkRequestViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 商品信息
|
||||
*
|
||||
* @return 商品信息状态流
|
||||
* @author Joker.X
|
||||
*/
|
||||
private val _goods = MutableStateFlow<Goods?>(null)
|
||||
val goods: StateFlow<Goods?> = _goods.asStateFlow()
|
||||
|
||||
/**
|
||||
* 发起商品信息请求,示例中固定传 id = 1
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onRequestClick() {
|
||||
ResultHandler.handleResultWithData(
|
||||
|
||||
@@ -10,6 +10,11 @@ import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 状态管理示例页 ViewModel
|
||||
*
|
||||
* @param navigator 应用导航器
|
||||
* @param userState 全局用户状态
|
||||
* @param counterState 计数器状态
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class StateManagementViewModel @Inject constructor(
|
||||
@@ -20,21 +25,30 @@ class StateManagementViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 对外暴露的计数器 StateFlow
|
||||
*
|
||||
* @return 计数器状态流
|
||||
* @author Joker.X
|
||||
*/
|
||||
val count: StateFlow<Int> = counterState.count
|
||||
|
||||
/**
|
||||
* +1
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun increase() = counterState.increase()
|
||||
|
||||
/**
|
||||
* -1
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun decrease() = counterState.decrease()
|
||||
|
||||
/**
|
||||
* 重置为 0
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun reset() = counterState.reset()
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.joker.kit.feature.main.model.DemoCardInfo
|
||||
* @param info 卡片数据
|
||||
* @param modifier 修饰符
|
||||
* @param onClick 点击回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
fun DemoCard(
|
||||
@@ -51,7 +52,8 @@ private fun DemoCardPreview() {
|
||||
DemoCard(
|
||||
info = DemoCardInfo(
|
||||
title = "示例组件",
|
||||
description = "预览展示 Demo 卡片默认样式。"
|
||||
description = "预览展示 Demo 卡片默认样式。",
|
||||
route = null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.joker.kit.navigation.routes.UserRoutes
|
||||
|
||||
/**
|
||||
* Demo 卡片静态数据源
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
object DemoCardData {
|
||||
|
||||
@@ -59,4 +61,4 @@ object DemoCardData {
|
||||
route = UserRoutes.Info
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ package com.joker.kit.feature.main.model
|
||||
*
|
||||
* @param title 标题
|
||||
* @param description 描述内容
|
||||
* @param route 跳转路由
|
||||
* @author Joker.X
|
||||
*/
|
||||
data class DemoCardInfo(
|
||||
val title: String,
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.joker.kit.navigation.routes.MainRoutes
|
||||
/**
|
||||
* 注册主页面路由
|
||||
*
|
||||
* @param navController NavHostController
|
||||
* @param sharedTransitionScope 共享转场作用域
|
||||
* @author Joker.X
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.joker.kit.feature.main.viewmodel.CoreDemoViewModel
|
||||
* Core Demo 路由
|
||||
*
|
||||
* @param viewModel Core Demo ViewModel
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun CoreDemoRoute(
|
||||
@@ -49,6 +50,7 @@ internal fun CoreDemoRoute(
|
||||
* @param cards Demo 卡片列表
|
||||
* @param counter 全局计数器值,大于 0 时在列表顶部展示
|
||||
* @param onCardClick 卡片点击回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun CoreDemoScreen(
|
||||
@@ -81,6 +83,7 @@ internal fun CoreDemoScreen(
|
||||
* 主页计数器提示
|
||||
*
|
||||
* @param counter 当前计数器值
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun CounterBanner(counter: Int) {
|
||||
@@ -94,6 +97,8 @@ private fun CounterBanner(counter: Int) {
|
||||
|
||||
/**
|
||||
* Core Demo 浅色预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -107,6 +112,8 @@ private fun CoreDemoPreview() {
|
||||
|
||||
/**
|
||||
* Core Demo 深色预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
|
||||
@@ -74,6 +74,11 @@ internal fun MainScreen(
|
||||
|
||||
/**
|
||||
* 主页面内容视图,包含底部导航和横向 Pager
|
||||
*
|
||||
* @param uiState UI 状态
|
||||
* @param onTabSelected Tab 切换回调
|
||||
* @param navController 导航控制器
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
@@ -126,6 +131,11 @@ private fun MainScreenContent(
|
||||
|
||||
/**
|
||||
* 自定义纯文字底部导航栏
|
||||
*
|
||||
* @param tabs 底部栏 Tab 列表
|
||||
* @param currentTab 当前选中 Tab
|
||||
* @param onTabSelected Tab 选择回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun MainBottomBar(
|
||||
|
||||
@@ -33,6 +33,8 @@ import com.joker.kit.navigation.results.DemoResultKey
|
||||
* Navigation Demo 路由
|
||||
*
|
||||
* @param viewModel Navigation Demo ViewModel
|
||||
* @param navController 用于监听结果的 NavController
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun NavigationDemoRoute(
|
||||
@@ -60,6 +62,9 @@ internal fun NavigationDemoRoute(
|
||||
*
|
||||
* @param cards Demo 卡片列表
|
||||
* @param isLoggedIn 是否已登录,登录后展示提示
|
||||
* @param demoResult 回传结果
|
||||
* @param onCardClick 卡片点击回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
internal fun NavigationDemoScreen(
|
||||
@@ -96,7 +101,9 @@ internal fun NavigationDemoScreen(
|
||||
|
||||
/**
|
||||
* 登录状态提示卡片
|
||||
* */
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun LoginStatusBanner() {
|
||||
Card(modifier = Modifier.fillMaxWidth()) {
|
||||
@@ -107,7 +114,12 @@ private fun LoginStatusBanner() {
|
||||
}
|
||||
}
|
||||
|
||||
/** 回传结果提示卡片 */
|
||||
/**
|
||||
* 回传结果提示卡片
|
||||
*
|
||||
* @param result 回传结果
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
private fun DemoResultBanner(result: DemoResult) {
|
||||
Card(modifier = Modifier.fillMaxWidth()) {
|
||||
@@ -120,6 +132,8 @@ private fun DemoResultBanner(result: DemoResult) {
|
||||
|
||||
/**
|
||||
* Navigation Demo 浅色预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
@@ -133,6 +147,8 @@ private fun NavigationDemoPreview() {
|
||||
|
||||
/**
|
||||
* Navigation Demo 深色预览
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
|
||||
@@ -14,6 +14,11 @@ import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Core Demo ViewModel
|
||||
*
|
||||
* @param navigator 导航管理器
|
||||
* @param userState 用户状态
|
||||
* @param counterState 计数器状态
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class CoreDemoViewModel @Inject constructor(
|
||||
@@ -28,9 +33,20 @@ class CoreDemoViewModel @Inject constructor(
|
||||
private val _cards = MutableStateFlow(DemoCardData.coreCards)
|
||||
val cards: StateFlow<List<DemoCardInfo>> = _cards.asStateFlow()
|
||||
|
||||
/** 全局计数器值 */
|
||||
/**
|
||||
* 全局计数器值
|
||||
*
|
||||
* @return 计数器状态流
|
||||
* @author Joker.X
|
||||
*/
|
||||
val count: StateFlow<Int> = counterState.count
|
||||
|
||||
/**
|
||||
* 处理卡片点击
|
||||
*
|
||||
* @param info 被点击的卡片信息
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onCardClick(info: DemoCardInfo) {
|
||||
info.route?.let { navigate(it) }
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ class MainViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 切换底部导航 tab
|
||||
*
|
||||
* @param tab 目标 Tab
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun selectTab(tab: MainTab) {
|
||||
if (tab == _uiState.value.currentTab) return
|
||||
@@ -41,6 +44,7 @@ class MainViewModel @Inject constructor(
|
||||
* Main 页面 UI 状态
|
||||
*
|
||||
* @param currentTab 当前底部栏 tab
|
||||
* @author Joker.X
|
||||
*/
|
||||
data class MainUiState(
|
||||
val currentTab: MainTab = MainTab.Core
|
||||
@@ -48,6 +52,9 @@ data class MainUiState(
|
||||
|
||||
/**
|
||||
* Main 页面底部栏 Tab
|
||||
*
|
||||
* @param title Tab 标题
|
||||
* @author Joker.X
|
||||
*/
|
||||
enum class MainTab(val title: String) {
|
||||
Core("Core"),
|
||||
@@ -58,6 +65,13 @@ enum class MainTab(val title: String) {
|
||||
companion object {
|
||||
val allTabs: List<MainTab> = values().toList()
|
||||
|
||||
/**
|
||||
* 根据索引获取 Tab
|
||||
*
|
||||
* @param index 底部栏索引
|
||||
* @return 对应的 Tab,超出范围返回 Core
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun fromIndex(index: Int): MainTab {
|
||||
return allTabs.getOrElse(index) { Core }
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Navigation Demo ViewModel
|
||||
*
|
||||
* @param navigator 导航管理器
|
||||
* @param userState 用户状态
|
||||
* @author Joker.X
|
||||
*/
|
||||
@HiltViewModel
|
||||
class NavigationDemoViewModel @Inject constructor(
|
||||
@@ -27,16 +31,33 @@ class NavigationDemoViewModel @Inject constructor(
|
||||
private val _cards = MutableStateFlow(DemoCardData.navigationCards)
|
||||
val cards: StateFlow<List<DemoCardInfo>> = _cards.asStateFlow()
|
||||
|
||||
/** 全局登录状态 */
|
||||
/**
|
||||
* 全局登录状态
|
||||
*
|
||||
* @return 登录状态流
|
||||
* @author Joker.X
|
||||
*/
|
||||
val isLoggedIn: StateFlow<Boolean> = userState.isLoggedIn
|
||||
|
||||
private val _demoResult = MutableStateFlow<DemoResult?>(null)
|
||||
val demoResult: StateFlow<DemoResult?> = _demoResult.asStateFlow()
|
||||
|
||||
/**
|
||||
* 处理卡片点击
|
||||
*
|
||||
* @param info 卡片信息
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onCardClick(info: DemoCardInfo) {
|
||||
info.route?.let { navigate(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理回传结果
|
||||
*
|
||||
* @param result 回传结果
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun onResultReceived(result: DemoResult) {
|
||||
_demoResult.value = result
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ internal fun UserInfoRoute(
|
||||
* 用户信息页面
|
||||
*
|
||||
* @param onBackClick 返回按钮回调
|
||||
* @param onLogoutClick 退出登录回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@@ -60,6 +61,7 @@ internal fun UserInfoScreen(
|
||||
* 用户信息内容
|
||||
*
|
||||
* @param modifier 修饰符
|
||||
* @param onLogoutClick 退出登录回调
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
|
||||
@@ -27,6 +27,8 @@ class UserInfoViewModel @Inject constructor(
|
||||
|
||||
/**
|
||||
* 一键退出登录(本地清空)
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
fun logout() {
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -9,6 +9,11 @@ import com.joker.kit.navigation.NavigationResultKey
|
||||
|
||||
/**
|
||||
* 监听返回结果扩展
|
||||
*
|
||||
* @param key 结果键,定义序列化/反序列化规则
|
||||
* @param onResult 结果回调
|
||||
* @param T 结果数据类型
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Composable
|
||||
fun <T> NavController.observeResult(
|
||||
|
||||
@@ -6,12 +6,36 @@ import kotlinx.serialization.json.Json
|
||||
|
||||
/**
|
||||
* Demo 结果回传示例:返回 DemoResult 数据类
|
||||
*
|
||||
* @author Joker.X
|
||||
*/
|
||||
object DemoResultKey : NavigationResultKey<DemoResult> {
|
||||
/**
|
||||
* 序列化结果
|
||||
*
|
||||
* @param value 待序列化的结果对象
|
||||
* @return 序列化后的字符串
|
||||
* @author Joker.X
|
||||
*/
|
||||
override fun serialize(value: DemoResult): Any = Json.encodeToString(value)
|
||||
|
||||
/**
|
||||
* 反序列化结果
|
||||
*
|
||||
* @param raw 原始保存的数据
|
||||
* @return 解析后的结果对象
|
||||
* @author Joker.X
|
||||
*/
|
||||
override fun deserialize(raw: Any): DemoResult = Json.decodeFromString(raw as String)
|
||||
}
|
||||
|
||||
/**
|
||||
* Demo 结果数据
|
||||
*
|
||||
* @param id 结果标识
|
||||
* @param message 结果信息
|
||||
* @author Joker.X
|
||||
*/
|
||||
@Serializable
|
||||
data class DemoResult(
|
||||
val id: Long,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.CoolMusic" parent="android:Theme.Material.Light.NoActionBar">
|
||||
<style name="Theme.AndroidProjectCompose" parent="android:Theme.Material.Light.NoActionBar">
|
||||
<!--启动界面背景颜色-->
|
||||
<item name="android:windowSplashScreenBackground">@color/black</item>
|
||||
<!--启动页图标-->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.CoolMusic" parent="android:Theme.Material.Light.NoActionBar">
|
||||
<style name="Theme.AndroidProjectCompose" parent="android:Theme.Material.Light.NoActionBar">
|
||||
<!--启动页背景颜色-->
|
||||
<item name="android:windowSplashScreenBackground">@color/white</item>
|
||||
<!--启动页图标-->
|
||||
|
||||
1
docs/images/graphs/logo.svg
Normal file
1
docs/images/graphs/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1764494784493" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11376" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M373.840702 202.347171H189.591355a67.836327 67.836327 0 0 0-67.617575 67.836327 65.646714 65.646714 0 0 0 65.647756 67.616533h188.190026l-1.968777-135.45286z" fill="#7585FF" p-id="11377" data-spm-anchor-id="a313x.search_index.0.i18.66f43a81iPdE0v" class=""></path><path d="M793.547376 805.21047H189.372602a67.836327 67.836327 0 0 1-67.398822-67.616533V269.744951a67.836327 67.836327 0 0 0 71.993675 68.05508h501.110891s98.470071-8.53449 98.470071 65.646714v401.763725z" fill="#465CFF" p-id="11378" data-spm-anchor-id="a313x.search_index.0.i16.66f43a81iPdE0v" class=""></path><path d="M474.501428 479.818603a37.638005 37.638005 0 1 0 14.44186 72.211386 37.419252 37.419252 0 0 0-14.442902-72.212427z" p-id="11379"></path><path d="M511.700885 565.596838a60.83415 60.83415 0 0 0-34.792133-109.411885h1.968776a57.550772 57.550772 0 0 1 10.722019 0V418.546948a12.035578 12.035578 0 0 0-5.68966-10.723061 11.816825 11.816825 0 0 0-12.034536 0 12.035578 12.035578 0 0 0-5.68966 10.723061v38.294264a61.052903 61.052903 0 0 0-26.697233 109.412926L328.106755 804.335458h72.649933l51.423607-109.412927a26.696192 26.696192 0 0 1 24.071156-15.098119 26.258686 26.258686 0 0 1 23.851362 15.098119l52.955919 109.412927h73.525987L511.699844 565.596838z m77.683334 228.016601a37.638005 37.638005 0 0 1-26.47848-64.115444 37.419252 37.419252 0 0 1 64.115444 26.477439 37.638005 37.638005 0 0 1-37.636964 37.638005z" fill="#3870B2" p-id="11380"></path><path d="M334.015168 235.609076h258.432634v47.485012H334.015168v-47.485012z" fill="#FFFFFF" p-id="11381"></path><path d="M454.368866 479.818603a37.419252 37.419252 0 1 1-26.697233 10.940772 38.075511 38.075511 0 0 1 26.697233-10.941813z m14.880408-21.883627V418.546948a12.035578 12.035578 0 0 0-5.68966-10.723061 11.816825 11.816825 0 0 0-12.035578 0 12.035578 12.035578 0 0 0-5.68966 10.723061v38.294264a61.052903 61.052903 0 0 0-26.696191 109.412926L279.308183 867.138384a33.260863 33.260863 0 0 0 2.407324 33.479616 33.698369 33.698369 0 0 0 30.417075 14.224149 33.04211 33.04211 0 0 0 27.133698-19.694014l93.220001-200.225604a26.915986 26.915986 0 0 1 24.071156-15.098119 26.258686 26.258686 0 0 1 23.851362 15.098119l95.626283 199.131839a33.04211 33.04211 0 1 0 59.521632-28.885804L491.568323 565.596838a60.615397 60.615397 0 0 0 21.882586-60.614355 61.271656 61.271656 0 0 0-43.765171-46.828754" fill="#073042" p-id="11382"></path><path d="M555.02855 277.404429a17.506485 17.506485 0 0 1-12.691837-29.979569 17.725238 17.725238 0 0 1 30.198322 12.473084 17.506485 17.506485 0 0 1-17.506485 17.506485m-194.535944 0a17.506485 17.506485 0 0 1-12.473084-29.979569 17.725238 17.725238 0 1 1 24.946168 24.946168 17.28669 17.28669 0 0 1-12.473084 5.033401M561.374468 171.272796l35.011929-60.83415a7.439683 7.439683 0 0 0-12.691837-7.438641l-35.449434 61.709161a220.575877 220.575877 0 0 0-180.750343 0l-35.667145-61.709161a7.439683 7.439683 0 0 0-6.34696-3.720883 8.096984 8.096984 0 0 0-6.345918 3.720883 7.439683 7.439683 0 0 0 0 7.439683l35.230681 60.83415a208.321545 208.321545 0 0 0-107.661862 166.525151h422.332751A208.321545 208.321545 0 0 0 561.374468 171.273838" fill="#3DDC84" p-id="11383"></path><path d="M732.933021 467.56323h-27.789957a3.501089 3.501089 0 0 0-3.50213 3.501089v438.745471a3.501089 3.501089 0 0 0 3.282336 3.500047h28.667051a60.83415 60.83415 0 0 0 60.614355-60.833108V406.730122a60.83415 60.83415 0 0 1-61.271655 60.83415z" fill="#7585FF" p-id="11384" data-spm-anchor-id="a313x.search_index.0.i19.66f43a81iPdE0v" class=""></path></svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
BIN
docs/images/group/qq.jpg
Normal file
BIN
docs/images/group/qq.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
BIN
docs/images/preview/page.png
Normal file
BIN
docs/images/preview/page.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 847 KiB |
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,7 +1,7 @@
|
||||
#Fri Nov 28 10:19:33 CST 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
Reference in New Issue
Block a user