|
@@ -1,165 +1,79 @@
|
|
|
-# 题库PLUS 客户端
|
|
|
|
|
|
|
+# 某人的题库 - 客户端
|
|
|
|
|
|
|
|
-C/S 架构数学题库管理系统 — Flutter 跨平台客户端(Android + Web)。
|
|
|
|
|
|
|
+高中数学题库管理系统 Flutter 客户端(Android)。
|
|
|
|
|
|
|
|
## 构建
|
|
## 构建
|
|
|
|
|
|
|
|
-### 环境要求
|
|
|
|
|
-
|
|
|
|
|
-- Flutter SDK ≥ 3.44
|
|
|
|
|
-- Android SDK 36+(compileSdk 36)
|
|
|
|
|
-- JDK 17
|
|
|
|
|
-
|
|
|
|
|
-### 调试构建
|
|
|
|
|
-
|
|
|
|
|
```bash
|
|
```bash
|
|
|
-cd tiku-client
|
|
|
|
|
flutter pub get
|
|
flutter pub get
|
|
|
-flutter build apk --debug # 调试版 APK(签名用 debug.keystore)
|
|
|
|
|
-flutter install -d <device_id> # 安装到设备
|
|
|
|
|
-```
|
|
|
|
|
|
|
|
|
|
-### 发布构建(签名)
|
|
|
|
|
|
|
+# 调试版
|
|
|
|
|
+flutter build apk --debug
|
|
|
|
|
|
|
|
-```bash
|
|
|
|
|
-# 1. 准备签名文件
|
|
|
|
|
|
|
+# 发布版(需签名文件)
|
|
|
cp key.jks android/app/key.jks
|
|
cp key.jks android/app/key.jks
|
|
|
cp keystore.properties android/app/keystore.properties
|
|
cp keystore.properties android/app/keystore.properties
|
|
|
-
|
|
|
|
|
-# keystore.properties 格式:
|
|
|
|
|
-# storeFile=key.jks
|
|
|
|
|
-# storePassword=xxxxx
|
|
|
|
|
-# keyAlias=xxxxx
|
|
|
|
|
-# keyPassword=xxxxx
|
|
|
|
|
-
|
|
|
|
|
-# 2. 构建
|
|
|
|
|
flutter build apk --release
|
|
flutter build apk --release
|
|
|
-
|
|
|
|
|
# 输出:build/app/outputs/flutter-apk/app-release.apk
|
|
# 输出:build/app/outputs/flutter-apk/app-release.apk
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-> **注意**:`key.jks` 和 `keystore.properties` 已加入 `.gitignore`。
|
|
|
|
|
-
|
|
|
|
|
-### Web 构建(可选)
|
|
|
|
|
-
|
|
|
|
|
-```bash
|
|
|
|
|
-flutter build web --release
|
|
|
|
|
-# 产物在 build/web/,复制到服务端 tiku-server/web/ 目录
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-## 目录结构
|
|
|
|
|
-
|
|
|
|
|
-```
|
|
|
|
|
-lib/
|
|
|
|
|
-├── main.dart # 入口,ProviderScope 包裹
|
|
|
|
|
-├── app.dart # MaterialApp + 底部导航 Shell
|
|
|
|
|
-├── models/ # 数据模型
|
|
|
|
|
-│ ├── problem.dart # 题目(Problem, SearchResult)
|
|
|
|
|
-│ ├── knowledge.dart # 知识点树节点
|
|
|
|
|
-│ ├── cart.dart # 试题篮
|
|
|
|
|
-│ └── stats.dart # 统计数据
|
|
|
|
|
-├── services/
|
|
|
|
|
-│ └── api_service.dart # Dio HTTP 客户端 + HMAC 签名拦截器
|
|
|
|
|
-├── providers/
|
|
|
|
|
-│ └── app_provider.dart # Riverpod Provider(连接状态、激活篮子)
|
|
|
|
|
-├── pages/
|
|
|
|
|
-│ ├── home/ # 题库首页
|
|
|
|
|
-│ │ └── home_page.dart # 三栏布局:知识树 | 题目列表 | 预览
|
|
|
|
|
-│ ├── search/ # 搜索页
|
|
|
|
|
-│ │ └── search_page.dart # FTS5 全文搜索
|
|
|
|
|
-│ ├── problem_detail/ # 题目详情
|
|
|
|
|
-│ │ └── problem_detail_page.dart # 渲染预览 + 标注对话框
|
|
|
|
|
-│ ├── carts/ # 试题篮
|
|
|
|
|
-│ │ ├── cart_list_page.dart # 多篮管理 + 激活切换
|
|
|
|
|
-│ │ └── cart_detail_page.dart # 篮子详情 + 逐题移除
|
|
|
|
|
-│ ├── export/ # 导出
|
|
|
|
|
-│ │ └── export_page.dart # 生成学生版/教师版 docx
|
|
|
|
|
-│ ├── import_/ # 导入
|
|
|
|
|
-│ │ └── import_page.dart # 系统文件选择器 + 上传进度
|
|
|
|
|
-│ └── settings/ # 设置
|
|
|
|
|
-│ └── settings_page.dart # 服务器地址 + Token 配置
|
|
|
|
|
-└── widgets/ # 可复用组件
|
|
|
|
|
- ├── knowledge_tree.dart # 5层可折叠知识点树
|
|
|
|
|
- ├── problem_card.dart # 题目列表卡片(加入/移除篮按钮)
|
|
|
|
|
- └── webview_render.dart # WebView(Android)/ IFrame(Web)题目渲染
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
## 首次使用
|
|
## 首次使用
|
|
|
|
|
|
|
|
-1. 打开应用 → 进入设置页
|
|
|
|
|
-2. 输入服务器地址(如 `http://数学.top:8765`)和 API Token
|
|
|
|
|
-3. 点击"连接"
|
|
|
|
|
-4. 连接成功后自动跳转到题库首页
|
|
|
|
|
-
|
|
|
|
|
-### 模拟器连接
|
|
|
|
|
|
|
+1. 打开应用 → 设置页
|
|
|
|
|
+2. 输入服务器地址和 Token → 连接
|
|
|
|
|
+3. 跳转题库首页
|
|
|
|
|
|
|
|
-Android 模拟器访问宿主机使用 `http://10.0.2.2:8765`。
|
|
|
|
|
|
|
+| 环境 | 服务器地址 |
|
|
|
|
|
+|------|-----------|
|
|
|
|
|
+| 模拟器 | `http://10.0.2.2:8765` |
|
|
|
|
|
+| 真机 | `http://服务器IP:8765` 或 `http://数学.top:8765` |
|
|
|
|
|
|
|
|
-## 功能导航
|
|
|
|
|
|
|
+## 页面导航
|
|
|
|
|
|
|
|
| 标签 | 功能 |
|
|
| 标签 | 功能 |
|
|
|
|------|------|
|
|
|------|------|
|
|
|
-| **题库** | 知识点树浏览 → 点击章节筛选题目 → 点击题目查看预览(公式+图片) → + 按钮加入试题篮 |
|
|
|
|
|
-| **搜索** | 输入关键词 → FTS5 全文搜索 → 点击结果查看详情 |
|
|
|
|
|
-| **试题篮** | 激活一个篮子(⚪→✓) → 查看/导出/删除篮子 |
|
|
|
|
|
-| **设置** | 服务器地址配置、断开连接 |
|
|
|
|
|
|
|
+| **题库** | 知识点筛选(🔍按钮)→ 题型筛选 → 题目列表(显示正文摘要)→ 点开预览(公式+图片)→ +/- 管理试题篮 |
|
|
|
|
|
+| **搜索** | 关键词全文搜索 |
|
|
|
|
|
+| **试题篮** | 查看/移除题目,导出 docx |
|
|
|
|
|
+| **设置** | 服务器配置、WebDAV 远程备份配置 |
|
|
|
|
|
|
|
|
-## 试题篮激活机制
|
|
|
|
|
|
|
+## 知识点筛选
|
|
|
|
|
|
|
|
-1. 进入"试题篮"标签页
|
|
|
|
|
-2. 点击篮子右侧的 ⚪ 按钮激活(变为 ✓)
|
|
|
|
|
-3. 返回"题库"页,所有 + 按钮加入题目都进这个篮子
|
|
|
|
|
-4. 已加入的题目显示红色移除按钮
|
|
|
|
|
-5. 切换激活后所有按钮状态自动刷新
|
|
|
|
|
|
|
+1. 右上角 🔍 按钮 → 弹出知识点树
|
|
|
|
|
+2. 展开章节浏览,点击 🔍 图标筛选该节点
|
|
|
|
|
+3. 点击叶子节点精确筛选
|
|
|
|
|
+4. 「全部题目」清除筛选
|
|
|
|
|
+5. 筛选后 AppBar 显示当前筛选名称,✕ 清除
|
|
|
|
|
|
|
|
-## 导入题目
|
|
|
|
|
|
|
+## 题目显示
|
|
|
|
|
|
|
|
-1. 题库页右上角 + → 进入导入页
|
|
|
|
|
-2. 选择入库类型(精选题/经典题/高考题)
|
|
|
|
|
-3. 点击上传区域 → 系统文件选择器 → 选择 `.docx` 文件
|
|
|
|
|
-4. 点击"开始导入" → 实时查看进度条
|
|
|
|
|
-5. 导入完成后显示新增/跳过/错误统计
|
|
|
|
|
|
|
+- 列表卡片显示题目前 80 字符摘要(body_preview)
|
|
|
|
|
+- 不显示 ID
|
|
|
|
|
+- 难度标签(易/中/难)+ 题型图标
|
|
|
|
|
+- 已加入试题篮的题目显示红色移除按钮
|
|
|
|
|
|
|
|
-## 题目渲染
|
|
|
|
|
|
|
+## 试题篮
|
|
|
|
|
|
|
|
-题目通过 WebView 加载服务端渲染的完整 HTML 页面(含 MathJax),支持:
|
|
|
|
|
-- 行内公式(`\(...\)` LaTeX 语法)
|
|
|
|
|
-- 行间公式
|
|
|
|
|
-- Base64 内嵌图片
|
|
|
|
|
-- 宋体中文排版
|
|
|
|
|
-- 答案/解析隐藏/显示切换
|
|
|
|
|
|
|
+- 单一默认篮子,自动创建
|
|
|
|
|
+- 显示题目摘要而非 ID
|
|
|
|
|
+- 支持导出学生版/教师版 docx
|
|
|
|
|
+- 下拉刷新
|
|
|
|
|
|
|
|
## API 认证
|
|
## API 认证
|
|
|
|
|
|
|
|
-客户端通过 Dio 拦截器自动给每个请求添加签名头:
|
|
|
|
|
|
|
+Dio 拦截器自动给所有请求添加签名头:
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
X-Timestamp: <unix_timestamp>
|
|
X-Timestamp: <unix_timestamp>
|
|
|
X-Signature: HMAC-SHA256(token, METHOD+PATH+timestamp) → hex
|
|
X-Signature: HMAC-SHA256(token, METHOD+PATH+timestamp) → hex
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-签名在 Dio 拦截器中透明计算,业务代码无需关心。
|
|
|
|
|
-
|
|
|
|
|
## 依赖
|
|
## 依赖
|
|
|
|
|
|
|
|
| 包 | 用途 |
|
|
| 包 | 用途 |
|
|
|
|------|------|
|
|
|------|------|
|
|
|
-| `flutter_riverpod` | 状态管理 |
|
|
|
|
|
-| `dio` | HTTP 客户端 |
|
|
|
|
|
-| `webview_flutter` | WebView 题目渲染 |
|
|
|
|
|
-| `shared_preferences` | 服务器配置本地持久化 |
|
|
|
|
|
-| `crypto` | HMAC-SHA256 签名 |
|
|
|
|
|
-| `intl` | 国际化 |
|
|
|
|
|
-
|
|
|
|
|
-## Android 权限
|
|
|
|
|
-
|
|
|
|
|
-```xml
|
|
|
|
|
-<uses-permission android:name="android.permission.INTERNET"/>
|
|
|
|
|
-<application android:usesCleartextTraffic="true" ...>
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-网络访问 + 明文 HTTP(内网使用)。
|
|
|
|
|
-
|
|
|
|
|
-## 图标
|
|
|
|
|
-
|
|
|
|
|
-应用图标为蓝底白 Σ(求和符号),通过 Python PIL 生成各密度 PNG,含自适应图标前景层。
|
|
|
|
|
|
|
+| flutter_riverpod | 状态管理 |
|
|
|
|
|
+| dio | HTTP 客户端 |
|
|
|
|
|
+| webview_flutter | WebView 题目渲染(公式+图片) |
|
|
|
|
|
+| shared_preferences | 服务器配置本地持久化 |
|
|
|
|
|
+| crypto | HMAC-SHA256 签名 |
|