From 71bc2db9856250bbe9c510c8aa6c114cdb917f2b Mon Sep 17 00:00:00 2001
From: ni ziyi <310925901@qq.com>
Date: Fri, 12 Dec 2025 16:49:06 +0800
Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AF=E5=88=9D=E5=A7=8B=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 132 +++
.hbuilderx/launch.json | 23 +
App.vue | 20 +
DEBUG.md | 82 ++
DIAGNOSIS.md | 74 ++
FILES_CHECKLIST.md | 67 ++
ICONS_GUIDE.md | 174 ++++
QUICK_FIX.md | 83 ++
README.md | 158 +++
TROUBLESHOOTING.md | 47 +
api/auth.js | 20 +
api/bill.js | 35 +
api/category.js | 30 +
api/ocr.js | 15 +
api/statistics.js | 25 +
common/uni-ui.scss | 120 +++
components/uni-section/config.json | 12 +
components/uni-section/readme.md | 30 +
components/uni-section/uni-section.vue | 136 +++
index.html | 26 +
main.js | 12 +
manifest.json | 71 ++
package-lock.json | 906 ++++++++++++++++++
package.json | 21 +
pages.json | 74 ++
pages/add/add.vue | 895 +++++++++++++++++
pages/add/list/list.vue | 158 +++
pages/bill/detail.vue | 492 ++++++++++
pages/category/category.vue | 337 +++++++
pages/index/index.vue | 297 ++++++
pages/login/login-simple.vue | 22 +
pages/login/login.vue | 205 ++++
pages/statistics/statistics.vue | 246 +++++
static/css/common.css | 80 ++
static/tabbar/README.md | 111 +++
static/tabbar/add-active.png | Bin 0 -> 8685 bytes
static/tabbar/add.png | Bin 0 -> 8594 bytes
static/tabbar/home-active.png | Bin 0 -> 7833 bytes
static/tabbar/home.png | Bin 0 -> 7657 bytes
static/tabbar/statistic-active.png | Bin 0 -> 1737 bytes
static/tabbar/statistics.png | Bin 0 -> 1729 bytes
store/user.js | 47 +
tsconfig.json | 27 +
uni.scss | 75 ++
uniCloud-alipay/database/db_init.json | 427 +++++++++
.../database/opendb-news-articles.schema.json | 122 +++
uni_modules/uni-badge/changelog.md | 14 +
.../components/uni-badge/uni-badge.vue | 252 +++++
uni_modules/uni-badge/package.json | 84 ++
uni_modules/uni-badge/readme.md | 58 ++
uni_modules/uni-config-center/changelog.md | 4 +
uni_modules/uni-config-center/package.json | 80 ++
uni_modules/uni-config-center/readme.md | 93 ++
.../common/uni-config-center/index.js | 1 +
.../common/uni-config-center/package.json | 13 +
uni_modules/uni-icons/changelog.md | 4 +
.../uni-icons/components/uni-icons/icons.js | 132 +++
.../components/uni-icons/uni-icons.uvue | 91 ++
.../components/uni-icons/uni-icons.vue | 71 ++
.../uni-icons/components/uni-icons/uni.ttf | Bin 0 -> 26164 bytes
.../components/uni-icons/uniicons.css | 664 +++++++++++++
.../components/uni-icons/uniicons.ttf | Bin 0 -> 35824 bytes
.../components/uni-icons/uniicons_file.ts | 664 +++++++++++++
.../components/uni-icons/uniicons_file_vue.js | 649 +++++++++++++
uni_modules/uni-icons/package.json | 82 ++
uni_modules/uni-icons/readme.md | 46 +
uni_modules/uni-id/changelog.md | 24 +
uni_modules/uni-id/package.json | 80 ++
uni_modules/uni-id/readme.md | 33 +
.../cloudfunctions/common/uni-id/LICENSE.md | 201 ++++
.../cloudfunctions/common/uni-id/index.js | 1 +
.../common/uni-id/package-lock.json | 11 +
.../cloudfunctions/common/uni-id/package.json | 20 +
uni_modules/uni-list/changelog.md | 7 +
.../components/uni-list-ad/uni-list-ad.vue | 107 +++
.../uni-list-chat/uni-list-chat.scss | 58 ++
.../uni-list-chat/uni-list-chat.vue | 533 +++++++++++
.../uni-list-item/uni-list-item.vue | 438 +++++++++
.../uni-list/components/uni-list/uni-list.vue | 106 ++
.../components/uni-list/uni-refresh.vue | 65 ++
.../components/uni-list/uni-refresh.wxs | 87 ++
uni_modules/uni-list/package.json | 87 ++
uni_modules/uni-list/readme.md | 347 +++++++
uni_modules/uni-load-more/changelog.md | 6 +
.../uni-load-more/uni-load-more.vue | 362 +++++++
uni_modules/uni-load-more/package.json | 82 ++
uni_modules/uni-load-more/readme.md | 70 ++
uni_modules/uni-scss/changelog.md | 8 +
uni_modules/uni-scss/index.scss | 1 +
uni_modules/uni-scss/package.json | 82 ++
uni_modules/uni-scss/readme.md | 4 +
uni_modules/uni-scss/styles/index.scss | 7 +
.../uni-scss/styles/setting/_border.scss | 3 +
.../uni-scss/styles/setting/_color.scss | 66 ++
.../uni-scss/styles/setting/_radius.scss | 55 ++
.../uni-scss/styles/setting/_space.scss | 56 ++
.../uni-scss/styles/setting/_styles.scss | 167 ++++
.../uni-scss/styles/setting/_text.scss | 24 +
.../uni-scss/styles/setting/_variables.scss | 146 +++
.../uni-scss/styles/tools/functions.scss | 19 +
uni_modules/uni-scss/theme.scss | 31 +
uni_modules/uni-scss/variables.scss | 62 ++
utils/date.js | 59 ++
utils/request.js | 185 ++++
104 files changed, 12636 insertions(+)
create mode 100644 .gitignore
create mode 100644 .hbuilderx/launch.json
create mode 100644 App.vue
create mode 100644 DEBUG.md
create mode 100644 DIAGNOSIS.md
create mode 100644 FILES_CHECKLIST.md
create mode 100644 ICONS_GUIDE.md
create mode 100644 QUICK_FIX.md
create mode 100644 README.md
create mode 100644 TROUBLESHOOTING.md
create mode 100644 api/auth.js
create mode 100644 api/bill.js
create mode 100644 api/category.js
create mode 100644 api/ocr.js
create mode 100644 api/statistics.js
create mode 100644 common/uni-ui.scss
create mode 100644 components/uni-section/config.json
create mode 100644 components/uni-section/readme.md
create mode 100644 components/uni-section/uni-section.vue
create mode 100644 index.html
create mode 100644 main.js
create mode 100644 manifest.json
create mode 100644 package-lock.json
create mode 100644 package.json
create mode 100644 pages.json
create mode 100644 pages/add/add.vue
create mode 100644 pages/add/list/list.vue
create mode 100644 pages/bill/detail.vue
create mode 100644 pages/category/category.vue
create mode 100644 pages/index/index.vue
create mode 100644 pages/login/login-simple.vue
create mode 100644 pages/login/login.vue
create mode 100644 pages/statistics/statistics.vue
create mode 100644 static/css/common.css
create mode 100644 static/tabbar/README.md
create mode 100644 static/tabbar/add-active.png
create mode 100644 static/tabbar/add.png
create mode 100644 static/tabbar/home-active.png
create mode 100644 static/tabbar/home.png
create mode 100644 static/tabbar/statistic-active.png
create mode 100644 static/tabbar/statistics.png
create mode 100644 store/user.js
create mode 100644 tsconfig.json
create mode 100644 uni.scss
create mode 100644 uniCloud-alipay/database/db_init.json
create mode 100644 uniCloud-alipay/database/opendb-news-articles.schema.json
create mode 100644 uni_modules/uni-badge/changelog.md
create mode 100644 uni_modules/uni-badge/components/uni-badge/uni-badge.vue
create mode 100644 uni_modules/uni-badge/package.json
create mode 100644 uni_modules/uni-badge/readme.md
create mode 100644 uni_modules/uni-config-center/changelog.md
create mode 100644 uni_modules/uni-config-center/package.json
create mode 100644 uni_modules/uni-config-center/readme.md
create mode 100644 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js
create mode 100644 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json
create mode 100644 uni_modules/uni-icons/changelog.md
create mode 100644 uni_modules/uni-icons/components/uni-icons/icons.js
create mode 100644 uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
create mode 100644 uni_modules/uni-icons/components/uni-icons/uni-icons.vue
create mode 100644 uni_modules/uni-icons/components/uni-icons/uni.ttf
create mode 100644 uni_modules/uni-icons/components/uni-icons/uniicons.css
create mode 100644 uni_modules/uni-icons/components/uni-icons/uniicons.ttf
create mode 100644 uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
create mode 100644 uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js
create mode 100644 uni_modules/uni-icons/package.json
create mode 100644 uni_modules/uni-icons/readme.md
create mode 100644 uni_modules/uni-id/changelog.md
create mode 100644 uni_modules/uni-id/package.json
create mode 100644 uni_modules/uni-id/readme.md
create mode 100644 uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/LICENSE.md
create mode 100644 uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/index.js
create mode 100644 uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/package-lock.json
create mode 100644 uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/package.json
create mode 100644 uni_modules/uni-list/changelog.md
create mode 100644 uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
create mode 100644 uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
create mode 100644 uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
create mode 100644 uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
create mode 100644 uni_modules/uni-list/components/uni-list/uni-list.vue
create mode 100644 uni_modules/uni-list/components/uni-list/uni-refresh.vue
create mode 100644 uni_modules/uni-list/components/uni-list/uni-refresh.wxs
create mode 100644 uni_modules/uni-list/package.json
create mode 100644 uni_modules/uni-list/readme.md
create mode 100644 uni_modules/uni-load-more/changelog.md
create mode 100644 uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
create mode 100644 uni_modules/uni-load-more/package.json
create mode 100644 uni_modules/uni-load-more/readme.md
create mode 100644 uni_modules/uni-scss/changelog.md
create mode 100644 uni_modules/uni-scss/index.scss
create mode 100644 uni_modules/uni-scss/package.json
create mode 100644 uni_modules/uni-scss/readme.md
create mode 100644 uni_modules/uni-scss/styles/index.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_border.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_color.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_radius.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_space.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_styles.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_text.scss
create mode 100644 uni_modules/uni-scss/styles/setting/_variables.scss
create mode 100644 uni_modules/uni-scss/styles/tools/functions.scss
create mode 100644 uni_modules/uni-scss/theme.scss
create mode 100644 uni_modules/uni-scss/variables.scss
create mode 100644 utils/date.js
create mode 100644 utils/request.js
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5f19c63
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,132 @@
+# ======================
+# 操作系统 & 编辑器
+# ======================
+.DS_Store
+Thumbs.db
+ehthumbs.db
+Icon?
+desktop.ini
+*.swp
+*.swo
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.idea/
+*.sublime-project
+*.sublime-workspace
+
+# ======================
+# 日志 & 临时文件
+# ======================
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# ======================
+# 依赖目录
+# ======================
+node_modules/
+jspm_packages/
+bower_components/
+.mvn/
+target/
+build/
+dist/
+out/
+coverage/
+
+# ======================
+# 环境变量 & 敏感配置
+# ======================
+.env
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+config/local.*
+secrets.yml
+
+# ======================
+# 构建产物(前端)
+# ======================
+/public/build
+/public/hot
+/public/dist
+/assets/*.min.js
+/assets/*.min.css
+
+# ======================
+# Python
+# ======================
+__pycache__/
+*.py[cod]
+*$py.class
+*.so
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+venv/
+ENV/
+.env
+
+# ======================
+# Java / Maven / Gradle
+# ======================
+*.class
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+hs_err_pid*
+.gradle/
+build/
+!gradle/wrapper/gradle-wrapper.jar
+
+# ======================
+# Docker
+# ======================
+.dockerignore
+docker-compose.override.yml
+
+# ======================
+# 其他
+# ======================
+*.tmp
+*.bak
+*.orig
+*.rej
+*~
+.swp
+.lock
+.nyc_output/
+.grunt/
+gulpfile.js
+package-lock.json # 可选:有些团队会提交它
+yarn.lock # 可选:通常建议提交 yarn.lock
+pnpm-lock.yaml # 可选:通常建议提交
+/node_modules/
diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json
new file mode 100644
index 0000000..6dea3f8
--- /dev/null
+++ b/.hbuilderx/launch.json
@@ -0,0 +1,23 @@
+{
+ "version" : "2.0.0",
+ "configurations" : [
+ {
+ "name" : "运行到H5",
+ "request" : "launch",
+ "runtime" : "h5",
+ "type" : "uni-app",
+ "url" : "http://localhost:8080"
+ },
+ {
+ "default" : {
+ "launchtype" : "local"
+ },
+ "h5" : {
+ "launchtype" : "local"
+ },
+ "provider" : "alipay",
+ "type" : "uniCloud"
+ }
+ ]
+}
+
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..5148124
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,20 @@
+
+
+
diff --git a/DEBUG.md b/DEBUG.md
new file mode 100644
index 0000000..1717c61
--- /dev/null
+++ b/DEBUG.md
@@ -0,0 +1,82 @@
+# 调试指南 - 空白页面问题
+
+## 可能的原因和解决方案
+
+### 1. 检查浏览器控制台
+打开浏览器开发者工具(F12),查看Console标签页,看是否有JavaScript错误。
+
+### 2. 检查网络请求
+在Network标签页,查看是否有资源加载失败(红色标记)。
+
+### 3. 检查uni-app配置
+确保项目被HBuilderX识别为uni-app项目:
+- `manifest.json` 存在且配置正确
+- `pages.json` 存在且配置正确
+- `App.vue` 存在
+
+### 4. 尝试以下操作
+
+#### 方法一:使用HBuilderX的标准运行方式
+1. 关闭当前运行
+2. 在HBuilderX中:运行 → 运行到浏览器 → Chrome
+3. 不要使用命令行运行
+
+#### 方法二:检查项目类型
+确保HBuilderX识别项目类型为"uni-app项目":
+- 右键项目根目录
+- 查看项目类型
+
+#### 方法三:清除缓存
+```bash
+cd frontend
+rm -rf node_modules/.vite
+rm -rf .hbuilderx
+```
+
+#### 方法四:检查页面路由
+确保 `pages.json` 中第一个页面路径正确:
+```json
+{
+ "pages": [
+ {
+ "path": "pages/index/index", // 确保这个文件存在
+ ...
+ }
+ ]
+}
+```
+
+### 5. 常见错误
+
+#### 错误:Cannot find module 'vue'
+**解决**:执行 `npm install vue pinia`
+
+#### 错误:Failed to parse .vue files
+**解决**:已安装 `@vitejs/plugin-vue`
+
+#### 错误:空白页面
+**可能原因**:
+- main.js格式不正确
+- App.vue缺少template
+- 页面路由配置错误
+- JavaScript运行时错误
+
+### 6. 调试步骤
+
+1. **打开浏览器控制台**(F12)
+2. **查看Console错误**
+3. **查看Network请求**
+4. **检查页面元素**(Elements标签)
+5. **提供错误信息**以便进一步排查
+
+## 如果仍然空白
+
+请提供以下信息:
+1. 浏览器控制台的错误信息(Console标签)
+2. 网络请求状态(Network标签,是否有404或500错误)
+3. HBuilderX的运行日志
+4. 页面源代码(右键页面 → 查看网页源代码)
+
+
+
+
diff --git a/DIAGNOSIS.md b/DIAGNOSIS.md
new file mode 100644
index 0000000..5fbc858
--- /dev/null
+++ b/DIAGNOSIS.md
@@ -0,0 +1,74 @@
+# 诊断指南 - 页面空白问题
+
+## 当前状态
+- ✅ main.js 已加载完成
+- ❌ 页面显示空白
+- ❌ Console没有页面相关的输出
+
+## 可能的原因
+
+### 1. uni-app路由系统未初始化
+uni-app在HBuilderX中运行时,需要特殊的路由系统。如果路由系统没有正确初始化,页面就不会显示。
+
+### 2. 页面组件未加载
+如果控制台没有"登录页面加载成功"的输出,说明页面组件根本没有加载。
+
+### 3. App.vue的template是空的
+App.vue只有一个空的view标签,uni-app可能无法正确渲染。
+
+## 排查步骤
+
+### 步骤1:检查控制台输出
+请查看浏览器控制台,告诉我:
+- 是否有"登录页面加载成功"的输出?
+- 是否有"App Launch"的输出?
+- 是否有任何错误信息?
+
+### 步骤2:检查Network标签
+查看Network标签,检查:
+- `pages/login/login-simple.vue` 是否加载?
+- 是否有404错误?
+- 是否有其他失败的请求?
+
+### 步骤3:检查页面元素
+在Elements标签中,检查:
+- `#app` 元素是否存在?
+- 是否有内容被渲染?
+- 是否有uni-app的路由容器?
+
+## 解决方案
+
+### 方案1:检查HBuilderX项目类型
+确保HBuilderX识别为"uni-app项目":
+- 右键项目文件夹
+- 查看项目类型
+- 如果不是uni-app,可能需要重新创建项目
+
+### 方案2:使用HBuilderX的标准运行方式
+- 不要使用命令行运行
+- 使用HBuilderX菜单:运行 → 运行到浏览器
+- 确保选择的是"uni-app"运行方式
+
+### 方案3:检查manifest.json
+确保manifest.json配置正确:
+- vueVersion: "3"
+- 其他配置正确
+
+## 请提供以下信息
+
+1. **控制台输出**:
+ - 是否有"登录页面加载成功"?
+ - 是否有"App Launch"?
+ - 是否有任何错误?
+
+2. **Network标签**:
+ - login-simple.vue是否加载?
+ - 状态码是什么?
+
+3. **Elements标签**:
+ - #app元素的内容是什么?
+ - 是否有任何内容被渲染?
+
+
+
+
diff --git a/FILES_CHECKLIST.md b/FILES_CHECKLIST.md
new file mode 100644
index 0000000..f0f40df
--- /dev/null
+++ b/FILES_CHECKLIST.md
@@ -0,0 +1,67 @@
+# 前端文件清单
+
+## 已创建的文件
+
+### 核心配置文件
+- ✅ `package.json` - 项目依赖配置
+- ✅ `pages.json` - 页面路由配置
+- ✅ `manifest.json` - uni-app应用配置
+- ✅ `main.js` - 应用入口文件
+- ✅ `App.vue` - 应用根组件
+- ✅ `vite.config.js` - Vite构建配置
+- ✅ `tsconfig.json` - TypeScript配置
+- ✅ `uni.scss` - uni-app样式变量
+
+### 工具类文件
+- ✅ `utils/request.js` - HTTP请求封装(包含JWT token管理)
+- ✅ `utils/date.js` - 日期工具函数
+
+### 状态管理
+- ✅ `store/user.js` - 用户状态管理(Pinia store)
+
+### API接口封装
+- ✅ `api/auth.js` - 认证相关API(注册、登录)
+- ✅ `api/bill.js` - 账单相关API(CRUD操作)
+- ✅ `api/category.js` - 分类相关API
+- ✅ `api/statistics.js` - 统计相关API
+- ✅ `api/ocr.js` - OCR识别API
+
+### 页面文件
+- ✅ `pages/login/login.vue` - 登录/注册页面
+- ✅ `pages/index/index.vue` - 首页(账单列表)
+- ✅ `pages/add/add.vue` - 添加账单页面(手动+OCR)
+- ✅ `pages/statistics/statistics.vue` - 统计页面
+- ✅ `pages/category/category.vue` - 分类管理页面
+
+### 样式文件
+- ✅ `static/css/common.css` - 全局公共样式
+
+## 可选文件(需要时添加)
+
+### TabBar图标(可选)
+如果需要显示底部导航栏图标,需要添加以下图片文件:
+- `static/tabbar/home.png` - 首页图标
+- `static/tabbar/home-active.png` - 首页选中图标
+- `static/tabbar/add.png` - 记账图标
+- `static/tabbar/add-active.png` - 记账选中图标
+- `static/tabbar/statistics.png` - 统计图标
+- `static/tabbar/statistics-active.png` - 统计选中图标
+
+如果没有这些图标,tabBar会显示文字但不显示图标,功能不受影响。
+
+## 文件说明
+
+所有核心功能文件都已创建完成,项目可以直接运行。如果遇到问题,请检查:
+
+1. 是否已安装依赖:`npm install`
+2. 后端服务是否已启动
+3. API地址配置是否正确(`utils/request.js`中的BASE_URL)
+
+
+
+
+
+
+
+
+
diff --git a/ICONS_GUIDE.md b/ICONS_GUIDE.md
new file mode 100644
index 0000000..469e728
--- /dev/null
+++ b/ICONS_GUIDE.md
@@ -0,0 +1,174 @@
+# 图标文件使用指南
+
+## 📋 项目中使用的图标文件
+
+### 1. TabBar 底部导航图标(必需)
+
+在 `pages.json` 中配置的 TabBar 需要以下 6 个图标文件:
+
+| 图标名称 | 用途 | 路径 |
+|---------|------|------|
+| `home.png` | 首页(未选中) | `static/tabbar/home.png` |
+| `home-active.png` | 首页(选中) | `static/tabbar/home-active.png` |
+| `add.png` | 记账(未选中) | `static/tabbar/add.png` |
+| `add-active.png` | 记账(选中) | `static/tabbar/add-active.png` |
+| `statistics.png` | 统计(未选中) | `static/tabbar/statistics.png` |
+| `statistics-active.png` | 统计(选中) | `static/tabbar/statistics-active.png` |
+
+**图标规格**:
+- 尺寸:81px × 81px(@2x)或 40px × 40px(@1x)
+- 格式:PNG(支持透明背景)
+- 颜色:
+ - 未选中:#7A7E83(灰色)
+ - 选中:#667eea(紫色)
+
+### 2. 分类图标(使用 Emoji,无需文件)
+
+代码中使用 Emoji 作为分类图标,例如:
+- 📦 默认分类
+- 🍔 餐饮
+- 👕 服装
+- 🏠 住房
+- 🚗 交通
+- 等等...
+
+这些图标存储在数据库中,不需要图标文件。
+
+### 3. 功能图标(使用 Emoji,无需文件)
+
+- 📷 上传图片图标(在 OCR 页面)
+
+## 🚀 快速获取图标的方法
+
+### 方法1:使用在线图标库(推荐)
+
+#### IconFont(阿里巴巴图标库)
+1. 访问:https://www.iconfont.cn/
+2. 注册/登录账号
+3. 搜索关键词:
+ - "首页" 或 "home"
+ - "添加" 或 "add" 或 "plus"
+ - "统计" 或 "statistics" 或 "chart"
+4. 选择图标,点击下载
+5. 选择 PNG 格式,尺寸选择 81×81
+6. 下载后重命名并放入 `static/tabbar/` 目录
+
+#### Flaticon
+1. 访问:https://www.flaticon.com/
+2. 搜索图标
+3. 下载 PNG 格式(免费账号需要注明来源)
+
+### 方法2:使用 AI 生成图标
+
+使用 ChatGPT、Midjourney 等 AI 工具生成图标:
+
+**提示词示例**:
+```
+生成一个简单的首页图标,极简风格,紫色主题,透明背景,81x81像素,PNG格式
+```
+
+### 方法3:临时解决方案(使用文字图标)
+
+如果暂时没有图标文件,可以修改 `pages.json`,移除图标路径,只显示文字:
+
+```json
+{
+ "tabBar": {
+ "list": [
+ {
+ "pagePath": "pages/index/index",
+ "text": "首页"
+ // 移除 iconPath 和 selectedIconPath
+ }
+ ]
+ }
+}
+```
+
+### 方法4:使用 uni-app 内置图标
+
+uni-app 支持使用字体图标,可以集成 iconfont:
+
+1. 访问 https://www.iconfont.cn/
+2. 创建项目,添加图标
+3. 下载字体文件
+4. 在项目中引入字体文件
+5. 使用类名引用图标
+
+## 📥 推荐的免费图标资源
+
+1. **IconFont** - https://www.iconfont.cn/
+ - 中文界面,搜索方便
+ - 免费使用,需登录
+
+2. **Flaticon** - https://www.flaticon.com/
+ - 图标丰富
+ - 免费使用需注明来源
+
+3. **Icons8** - https://icons8.com/
+ - 图标质量高
+ - 部分免费
+
+4. **Material Icons** - https://fonts.google.com/icons
+ - Google 官方图标库
+ - 完全免费
+
+5. **Font Awesome** - https://fontawesome.com/
+ - 图标库丰富
+ - 部分免费
+
+## 🎨 图标设计建议
+
+### 风格统一
+- 所有图标使用相同的设计风格
+- 线条粗细一致
+- 圆角或直角统一
+
+### 颜色方案
+- 未选中:灰色(#7A7E83)
+- 选中:紫色(#667eea,与主题色一致)
+
+### 尺寸规范
+- TabBar 图标:81px × 81px(@2x)
+- 确保图标在选中和未选中状态下清晰可辨
+
+## ⚠️ 注意事项
+
+1. **文件路径**:图标文件必须放在 `static/tabbar/` 目录下
+2. **文件命名**:文件名必须与 `pages.json` 中的配置完全一致(区分大小写)
+3. **文件格式**:使用 PNG 格式,支持透明背景
+4. **文件大小**:建议单个图标文件不超过 50KB
+5. **缺失处理**:如果图标文件不存在,TabBar 可能无法正常显示
+
+## 🔧 快速测试
+
+创建占位图标文件进行测试:
+
+1. 创建 6 个 81×81px 的纯色 PNG 图片
+2. 未选中状态使用灰色,选中状态使用紫色
+3. 放入 `static/tabbar/` 目录
+4. 运行项目查看效果
+
+## 📝 图标文件清单
+
+请确保以下文件存在:
+
+```
+frontend/static/tabbar/
+├── home.png ✅ 需要创建
+├── home-active.png ✅ 需要创建
+├── add.png ✅ 需要创建
+├── add-active.png ✅ 需要创建
+├── statistics.png ✅ 需要创建
+└── statistics-active.png ✅ 需要创建
+```
+
+## 💡 快速开始
+
+**最快的方式**:
+1. 访问 https://www.iconfont.cn/
+2. 搜索并下载 6 个图标(首页、添加、统计各 2 个)
+3. 重命名为对应文件名
+4. 放入 `static/tabbar/` 目录
+5. 完成!
+
diff --git a/QUICK_FIX.md b/QUICK_FIX.md
new file mode 100644
index 0000000..35c58b8
--- /dev/null
+++ b/QUICK_FIX.md
@@ -0,0 +1,83 @@
+# 快速修复指南 - 登录页不显示
+
+## 问题分析
+
+uni-app项目在HBuilderX中使用Vite时,可能存在路由系统不兼容的问题。
+
+## 解决方案
+
+### 方案一:使用HBuilderX标准运行方式(推荐)
+
+1. **删除或重命名 `vite.config.js`**
+ - HBuilderX有自己的构建系统,不需要Vite配置
+ - 已重命名为 `vite.config.js.bak`
+
+2. **在HBuilderX中运行**
+ - 运行 → 运行到浏览器 → Chrome
+ - 不要使用命令行运行
+
+3. **检查项目类型**
+ - 确保HBuilderX识别为"uni-app项目"
+ - 右键项目 → 查看项目类型
+
+### 方案二:检查浏览器控制台
+
+1. **打开浏览器开发者工具**(F12)
+2. **查看Console标签**,看是否有错误:
+ - 路由错误
+ - 模块加载错误
+ - JavaScript运行时错误
+
+3. **查看Network标签**,检查:
+ - `main.js` 是否加载成功
+ - `pages/login/login.vue` 是否加载成功
+ - 是否有404错误
+
+### 方案三:简化测试
+
+如果仍然不显示,创建一个最简单的测试页面:
+
+在 `pages/login/login.vue` 中,先测试最基础的内容:
+
+```vue
+
+
GH^1~yqs{xzRiLFz{EaO<+CA3 zmg2$ZwsbNi?Q4!ZP{T-?;%KPxF5ZVL8u82ZV)J+ij|^-1xAa?IzH_Cs@~RGNJ!78> z)qbsN=|L?DkE)@c-gcIH*o7~Q*@jsQ9)0hm!v?U2xX*Nph)zv<0EgtFV}Cbqb8 zrcq~o8YJ(*2<77Lu-P*FVtiF{!ip<&$gqeVv=2N;pTBZ?sFA{%v!PCN0sPQsBZt)U zu6?9CYn?9Q5(&M^HqicQ;U!o35d4+?+bd;g^+ DJ9A%UQ_|c2=K9MyjRMjCJS%_HB#PMK>AeOFKgL-uA0yVfn)3 zM5$t|92{N#ty;g7&_}k_NUB$Q0S!k8hMU|HUyL%Y?_lmlC|Q{@b`)MS6_S<+8vG$6 zsU?0vf^UgaxwUlY*WAFj^8*`$mt9O$pMd>?FuUHe`K%kuze!N<_M{CDnHkSn$g^^! z!`mPxh&W?=A)Rz@3$6Ji?J%L9(Q_dBe FSacaF1O z4K1CPi^7DH@{Ay4>1+_72cJ@q7KmQP?8 Ni*fZWM0FeFHa8^S`rfR>@ 5&ns{G?^OBi^>0#4qZ=N9rl#8mfWG z($PO$k2R4LmyW5nTr@=C07M2?jv$SZ#?jal*(&SSVHO>d-sEfHK$74^?z97G5#cc7 zi*Pws#~=Ce1q5M%r0&Rb>`4|#3VpwJaJJ8_>K@6Cx^uQ)CPg@c1jypZ;vZZ_th-^_ zJ>$46Uk{U{5NX1b-yvokWQlB$GVro(eZ#fOtP3=mYS%gi_vDf1aXQ~H{RF}$+r-#S zcDC96eWakB=zk)OX>t0RxE!@z^uVVc4`~!Q^2dQ6z|s%ZoU&FG@c4_Ro?ztCZ7%iC zI8Io$&gfW%wlsrm+IO^XJ!RmInuC&Cgs>=tjmRvxY Frq)XB>Vw|Jg*M9WK{= z0P8v;ff$H9$mGY%>iFAfVw+%wx$soK#E+^I0Zz3)$N|0g)XIeuFO5Ku^ hu$FOOI!_0@jjPGaN#YT^Bv6~{kDX3VNH;kPa2t0;Hp4Ou64(JbwbvOq&26QtFf zt*{4$G8eMH%D&&BgqRylay5s1u6v7F&3NzCo)guBY!6?>%jMSSumX#hT0jL?1un<` z{?#SNC6d7a%hLKe@g9rZ+4OJ(ADIMZ&C+8^#Z0FCNwrNe9E_=R3LCKxFe#N+nun}Y zVdO3|mFx$CyVqYH!eYvNR#^4aLa{^waWE)=EUheq!Ha~?NtF~*yeC2~&H%6r+Ek~& z dzJK ze9vzPAu@|uQBHhNWMHH_+PE99$U8n`NLX5>q}@8_X!|Mhk-&Eihymq#d@$SN33v7i zN8n?A5U0E`jbcC&-u}4{qsSi(Z696N6V+|j6Rh=+MOW@VT1B65_w+yN(m=fxvEHW2 zU865W+H38{`4A`fN~74;CszuFtuv7cxjZubt1Gt^_TNrjSzZveq#pA4l4@X^N}B(P za)FZWSMGd}=ecJCB`*ax*5D&dN-LGDx!X1@aC$rdAo{eJ*8g7%`0XIgH{%52Yw@AB z4H M#u)a(tDWKDbT#meh>bbow?)NqZUW=lzHcU+z zxU-Xwf>Rndvpfpa_SyjZo(6U2@j?w~Ex6WRB?rDdN#}wzCacApw8=-{MjTBA{EC-* zR&O{a{P^E(x43v8;BCqpj&R@xlaBH+1>UA?1_hen&qLs}eeQl+-$gO6`Yci*58lR+ zkZ#Y4TBh=ck*e-l_ws2|k{}A?U&VUvwc;{{IEkXeR!IepIWcSCVa#Wjn!9m(Y~ V}&TT+7 z2?VkrzB&5cP@m$d7c4Q4W-lQiAtG1_QI467AybFOTp~OgVFfi(HbnAH!~rkzN4xQm z`)kg^EVF8c-+N8By@%V^r%!>u--I@-lIL0BSjjmFe(5_&+iH0GtF$V7lSL$vnI%)8 zg?=C|6<$#Df8IIpp|g||p!UAzXGHgFO18)J3AVR~c4=AXEUQ~~xOU$E8{u)K^r+*e z5{FY{W7hJJOyd&CVOvR~4F99n{_!0;5zK9oZ;F9%BEF&OMJF*}I;iN~=mQ?+h(cA; z43F8?eKZFVZhN_o9z^GRJ@L1ZKizrP+Tgfqy((b8O~G#*JcCE2HAq30ZMUW3PBuhk zN47!)x2QRzB5_I-R0b(XvkfM?OkWcSCNDWg3c%XPKH^$~$LKgPN5n;H=m_#5OAjZx zj 35S|@jIP}t{2q0=Vz>9Jyc7M2gE322{K dO%5lj$` zf`1h@Y`?qSRTkbSuaLr+lKI^V1nJk0HbiVc&^%$^q3>_D8G*83DuBO5Idfh~=%bWb zaXBf}&jT%a%5yqLfW~=Qw`70^${!y|{64BhmuEe75AQigS99lyjpU>{ssmYNF@Zx5 zd!&9>JBcCcL6&r6=ASFAW_ZsKXn&gwbM76aY}o+A#8T`Za$f&TA|c_O_%!N&s|rmQ zL5alSMcm{e%%?`7t%>8`mgonIh%mlJ8O&L_4@HNJFOz0#a4%{UV$vUlBF~tfBFkFb zvX4lJEZL($8!fAfX-~eyT5uRw;*#oNcA2BpkYcl1)q?&_>2iW2SfGIRK5?PC6MtvY z nJtl3@^BDxB`d86#mZ_mz z>ZnM*p~IOH2g4GiGOluZtGlWZ3-IW?0zzN4s5={U;->0?grkh*B#rrVIIhvfGL*Dz zoA6}Y@U2`j^xww&TM#@Yn2kqz$i=gS1tfT)F6#El&Nh9C5`))J%uxtnlr_PUNB4Dn z{!|Wlp*DG_XeIjBb@4Y7J!01u3an^vSTYJ!NbZFHoTta?#w73eGCxqn`Fm$UmQSkn z{cr70F6NLR(YR_PVmoF#E>P-s7X{aRKIC)zb}it1uRv =nyr>L=Ab(lPpo9&<)@B7Wc$p!&OpkC)xEuSzR9bih~7fvJWYSR1@JZ?0SG zEe$Jt@?;H)XFdLB12 1hgcUikg`?B4oFTl_pz;Uor;L7qcfQP0d{ ziBjF~QVv{rC(j%c&{n;(w=K)XC!JE#= z^1%W;;0Upe_O`TB9-IXvU-of5qfK;h0+Fwn$wg4yEyGKx`VuK#mjP3I12Rhot%@eb zwKBAxFjVu*JNgAA+Uhe7ry0 abApxmaj z4Tsfdc4^drVC;dM^Y?M5nQ@x65O-ej0@5Lup2XB`O%^n^G*<~ghOWR7HXkp?iq|r= zO@EK=wj?ohCWgXvwG|!h5?_kzI(thPv(q!Jui6g!O0?K6q8STEldYK>Klt{6ouQr@ z3^%jkeXj9r!DFX%UJ~+bc;17`Ge p@A_mzw~jX0?8o1cXAu)&?%CK-G7?Yo%P@p}{Km~~$&nr6{o7bNHA z^!yax?USy1E9(*{p~d4Vj9kT*jCw0wL={mV_aqE3{|pcl&t-{<9Qvq&$J9Lc*^0`P zK7aH|rK7<^#*`?m#^*xb+4g%IQzzeAmrN=-oM+)p@SDZm$cm~)_vBp8F}-^Jj>Kd@ z+LloFT!&HXM_|)X>J8Jr#JMw-IIM&|MEar~QKvT747@P)s|Y}$s`*{SfD$v`iZkhc zQq2WVcR}+tSB>I(T;#!cEK$$A-xym>Ws}y_&A28_35vW-MD~p7d&&aa)H`K@i>|cV zeiHv6bX7`m6(kQGTq#O{S4V|6+4}o&KR@MnGE{KORJ(;)X?+wEj{ Zu4)$}}ct5CPLgAC63;Y_szP)CBPg_Z_Rd=7B# zE=}bO2h7MZzFPbQkOm2vy9s!&T#|;+JgRjL!&JC@*<<=Q?6w-;+}WZKg1HIL>P9@$ zYDaK^T>9Q$&FV @{(4ZNuu*d?H0~7)!pU#tuQ(*-+r?a>Dj5QG1}jgOpno!ir`t zrD7AcE4~=8?wS!-doDwp1R?t{LoS;Ea5pC5oIdH4TWjr9m(8`e(4u;x1t!E+|Ega{ zbX>Q&uECz2uw6<(aq}miNEM97&Ra|3WgS%&%>>VH2Gegx8yXG;St?vCDrx;+RdAA< zK+C%!*7bi?LDm@H&sIK9TB~Cf$inlb!kDh W3IY2EbzRaX%_fvc>w%zPU(9#478k3Z}=+D57Yq(u#4 zb9IMwrpdo9u3+l%t~sL5pJ4T%HmJuS7LkGhncrCHw=7TmqSkmcjNNonPkqd53+(Fr zZtI0=;$5j*L2;fmEAxS&K=LHBRd=?h7cMG-y_`)FNtWHOFTX@@^XrPDci=E9MTbj0 zE$vN}eycC+q?V@mCp)>UYsYVM1{bM@Pe!?YO@fm9q4ij{>(&^DZ-YcA<){6oqdsTh zX(yI0Js-@Df?y%8uKM>b)8_O7Odt0;-K2WEXm51mtB8;4YfgK~B%4odnfIH=JYrwi zyw7CyBX$!-YtzW4tS0k?q~hy&A0VmR<>GcCe`R=nhTMVzkLN`1{PT!Ctd1`&dXYgA zGo|A*yaDdGGLvZCnu%Z4jf`2fO0Lk{mJl;GT7UZGv_tr{=&+I=8NBZOTDpoq_ezVK zGFyz^9b1?l{p0wIpUa6sZuz@qzL=`E=g-tvSaD(%Z7`F#M=nd;OVGl5FW0A*ybmY{ z7N2S>_loGN=zxs)&+g*d7)|5wlKZ>yafXiR(zB(5<~^@o;bT5Gzlt_=S>@}j> y(Nxjkd^`O0q~X-dhxU+d35;O>xsNVj>p>usPIX-`KE`RTl0 zN7Gj=iqjo?mpP 7zIFPi0ofN z+taFt@KVhpUg#e(6C?z4=JIao$)AQ;Zv+F>Oa8}g<#ZDkiJ{E*3H$~WMdz#KHlun$ z11pZz!BJPET@|z^qHZ1@a|^cIOp6Q&vVT&l!I2H%VT-VRBhIfPKGFjBH-h6zN?*L1 z+f0lextbAjqDB(-pPh#*h5~$nfN|S56o*2LHgu%K%KhTd`Tqhg9c(J0=8e^$ybV&L zmut{3_HW8K8+h)wGxuX^7TlgNY^n!0)V-=r_;6!%e%kawTSYL}?DDqElI5RAYO|@U zIFe9q&u&Y7 y?YU?(;{BjvQ$mPKQLdQZ9 zK0!h!IEn$>e*+)Gyk_VzGOvTC-EQ@y`kAz_qNCsb)VOT#>hc@nJUbx^d4E%D=X~>~ zG#cA>dY=5uFVHWzFc$+a9-^68n6`NFeW!h!NK3?%&KP2OW)T6X%$9f_IbvvQ&Qec+ zgLXD!k?|-4VIcK%)1Ahqs@6Mf+UwY}@3FsFL-+lb!0%Cu=?g4Mu?A@G#+0os1(P3b z+76j&_Xx;leaVWp5;Qx?H3vCK$Z}Zr9+EV4eV=w~Tu!+aADpx`79(ouea0$+#;kjb zm5YI;0+>OCcjEZ3u1xmd`ZUdP^e?clMJ5%_0svsd{nr=p;mO*#?}|1fEbjYRR8$wO z5-(tyBopjy){E7?y3|N_gl3|v8h^DML!~D37v-`wq98OxA+yG}Er0Ercr%Rl?Z}lS z7jLgo2BEShuL;?=rQj)4q<<*^4 _ny+I&!G&2YISP4gjqCQT|eW1eT? z8$)~>8TU~)9%!0w;l|;k)LMq>@;AKp2!@j3N;jE9JMtwrEjl(5lBqHh@LL4v@(Z zPelnAMusC8Rm8+-c)8=ygLsiDJT5wP*Fx{tsQ~8}=z&R-wWiU=e+dyMnFjDnnqY-J p;sOAVkHZqouIQ!>od3QG7NCOlNRgB{Rth}>P*v1|*T`ET|3B?DIY$5h literal 0 HcmV?d00001 diff --git a/static/tabbar/add.png b/static/tabbar/add.png new file mode 100644 index 0000000000000000000000000000000000000000..5f5943142d0cfec59da7e42cb195595db9277b3e GIT binary patch literal 8594 zcmZu%by!r<(*|5&7X+4$C6=X>4rwXr?vj)Skq&8Ca_KGwq>)Z338e&#hUUjJdE&%lOBB4BMYI~-VcBjmKz?p=LQS!UuCc;T+2 zm+f{S^dMStpt(GaH=i!k1*_2lIKcOaDSdyyBrJ(~WP@eQ&>tmiXmO%e1T`RYi$@hS z3?ZhU7>x^Bq``EOT}(d{UZ(KXiv#BXJNO4*XZ~N2nIMs+d>0At(B^dqW3{LI0FGYB zOzhyEZw z`bQ|mTi>+9Lm>mu0|ol+xn|=%x %+nPA MUIxmDtZz6(o zWP5Ii#%Vqqw}#$bl8=nP<>s_>J{X3MqZ^NG<{R!t{@I mU*G1D!^t1XUb7!qSi<77 zYRJ57CNm-%Q{nRw3d$mt%Jd&J+3#iKbV&PlJ*((=39-KCmmamsPv<^buNAko65sif zfojJ)xp;e1t!UzGFo07|BL3>@l BLB*f!y0)g0|t_^%jKw1T_m`LU B{W#He**W1Y5a_vAkgvi>h9$zZ4T5v06u{fPbTI?h6zhoizt=I$mqI)8nN|4oR$Q z_RQ8@a*zW_;RDTroe8-X+0f*U&cGJRP(#?ZuK7JV0j-?H0|sW-Yc6#D#>VO0fc0ks z`b H-GJk&N z)8Ht6E88e#B+Tkn(lp;fBk-D& $^`oc$J8wyU(;jHie}t0bRTP&xSHgr{y0UC3&u>Xj(NG+)`xgYu z7}sK`R*nI&xZdq9sUNI7Fr2jS&ryl9dxRua-8DKso8P%uELdeZBw41Nt;TVyF;)La z#6LYNdERRJq7_qb@uF@`%h~NfzOk{!hSxbg$n)tw`a% er_ov-8`b)ZV^E`D~{_^f*-I`}F*+VStF`^-eOVftifk*o#hDdk}tvGIVioVt@K zK1{tcoJAC50$Q_19n51d(|^qKQlzi==2doJGHIWxiB*RJ8|Q1eH?0XTi597Tf$*p3 zk6X>%6He7*AmeSe{>Z+c<0AxVp6*r`M-({0C~J7aE^ddcnXVbigr0QA*sPU3kO8N* zEg*`26~XI9_&AAEFFd-#b?M#XyFD-Dzl0ckX %mNQa^b5p{Kj5S;e)Q{Q)~% zOwyV6ooI3^KwT7+V$*^Z8%T!&0#;V|FfMfFa%QpH54Q~LD3`VJye#NXf2~yLm|z*^ z!oG%ZgpT-1c&AxSFir4#>rUV-OMQguTN{~Fh3m2O+H8VSG#fxfcLFkoOn4GJ->6Sx zU;P= ;dA1v`uaq~Z*b7-aSTbW#frjmPU?Yy&pG7`-Ru~Hyx$~e6J2U+EJ^Ns zz|=&D;oG8lhqS}&>1K;sR C|P}>i@kvX)9t8p@N=?f0G#iDt(=8kVB363GcNs^)z!Wq zKjq0Z&tDKs;675Hsn4KFbD3RFA*LI@Z+Aqd i}7ahlldgt zZ~Ri(ndOvofEPZikomk(t1a%y^s%mpx0=^+Z{8orAy4BFu M9)C_)?1!Ev@g6@ zUu5nK>5oe={d0DFuQKtB#A*TFqw*}ii(Xr^mc^XJg(Gcxa_ltt3ve@qrI9trB$6R< z+kaU2C3)MEbSPtW+zn(m+n}pknzsLVb5K@2u{z8$Z( mALLAJRqoY5RiavPIJF6va4zZmYP`eR;9iCcz_c<^~rdMr5O`BT4GSiV= z4Dtgw95Sv{*}(+@as2e0Od l-U1E+;ROVauMmpEU6siO3xMrVG?fAk|$|Zp!8+pjN zLKeoIgQ7*XqF!tWJ# !dBdRBFA&+5%O{Xod%-6;=;%z@SDo7M>v{g{ zda*8RB@JsXE{6UNb^^n@NqdW}*dj4;s(dF9&(5^TmyDHUQt5mY`O^NKypO1^R2mSf zFjK2(7uaR#Uae*K8nk(?Mjuw2!g$ z&4I3!3OZQ6*8`s5p8G!pw$biecM+7%F6YXBEaKLBAy)o;lt#XwN5az)PX1hh1%?+@ zpm4RluH?&?rB)(30|6Ays%a4&Bvz!adQ(!j)`=>CU6iS&_?&(3QTi>E?*owml%$VJ z>E0IDz8AZAqgth7MEeGCcWT}oFD_ka%U9*wIh!;u0m3JJC~~bf?f7kaQH6wt6FdX0 z!-~j^ANHG=Aao;CRf4ZxG5;5u5jj`2gd{!R4na%2@Up?I)-T^uA
s0R#~R644cYB1 zj9WM!>f}m6>vOxi`tHf^;3><$wRs+{uZQgy2B?E%2nI9rhyyhy=X;Rb1e4{VYyPhM z9wVC$61me}i*qQ$E^?ph@4XvB-mM9S@RUDi{v=0~TI&Uox7&^auUFi!bD3FJ6`ygM ze9ch$LH{lK2=~O>?wy?*5pBlKWfElL{DGl`Au{GmEnD D%_7n+L$EIhKi;G=uQwVJKws2vjL#1j!t5aYBWZ6)>a;ctB54dUO$E= zkna`<&V2$=Vct^yrrK91HQ!1p>r{l;G)rgr&ZJ?mkgCx0szQ0 TM!OfF6UTFcoTqo!9KS ^qo$7*<3+>3n3=D;e>(VW|Q zbWl%tPb4}9b9JTe1#iMf`XmK-7pTC6mdN;3Kg_oa#)X64O+N1r$Cl+5D&PGe-~o5< zU@JBOznk>YYGU_T;FoORf{1Ua#-JXkKWVxXI#!9Xu$zA&>T&tBt`cLmY4i-M? QXN{9E=JHJO2F>n6?ZgABP-`;&qEZ++t#)D38Md!ky6A=t(D zO!B?>MHl+T@0wp9(gl)!VYRvHCqhS%ASnC~ubPuqK4f()@guZF SNjSm74r(e7)(ol6;2EZRYVEuWDU5%|Ah- zP9ya6eHN!4Awitwx 2vsRwwnWsQpkVwaI%d#NFp;34!o~@zjFXH@OW~P_q CO2qO@HkG?~?=!=5!XWWLErAo57IQf7x z1JUS~9d7BE^jCsDv6BW*0o^U^>eFCFKFLto6MXA7*P`jHG;eM|2I?mI$iXYeZZ;oc ztA^VUp`Q^*)neQW5_2Y=2Pgz3TPef^!CJ+Hydsh_bLZ!k?yIt)(ziwvevJqRxUISM zJee#S(U}t`lKX-!iDiYR@Pw89Y@ _E_E>{0oalt}!ZZDmEPAG?w+t-Io`0oYr(OtLFz=G{+* zZr!RodxO~d5iHE}=FxALlHF5qoQUUXq@8P0L@^@S_ieri;Zc9KKv=_{@6&`Xh8cQ1 ztNTV8TnHrZC3OoB1rqI?L8A_w8Wk^?J?4%L0Pf&O3mon=dFyb6FMfm@r<0@p4BU49 z^n_A8i@wO0G0R) !AxPBqNoIEF;?9RuIy$!;hmJ#W>pDUj?&p@fe?HG~dIF1!11w+6 z#@5=YWFstuyy0B?Wp>glw5)F)A;bWV(-I*GO%HB *nfQ^T>$){c#? zYO;5fwVwnfo$(o5W<1cxcw1RhrZI871QNBvI<(bhLcXz!$Vt?QmTXLS*14tSd>W79 zV^X9VLJ&!R*->xUFs5zmoOA)4tY&8v4M4gsb*u)%F#1PW19g-U t5?vQ?H$8UXQZV5 z_zW9lc~>z`g0^;6Ibox=A{jc6xJzFGD>`GX7t0cM)rp6l3xkd!!=(P9Oo2>$$iaXI zRw9P8)Kh|g6Hq-)kWVuasyu6}a&}TL5VETy{Vnllhfg$`)1KMN;+wWcyS_Ka`ZMxi z)lVMO1qPF-IBn9y;m@wGUbOP!80*Sm0D?SXyfJ3{^xZAk|E&vX#}v712$!dSDdi @l*R|OwzHEI@LP&+} zbEX}{ox*op87w^XO2GHqmo99~YTyYPa~0y~;T~~i3c;V1l2XAE0)0#`V^v;JDt>}i zT%xPc%abg;QA-$`cDiE62 S1w>WFY&HQ=P%~1Cadw42@}Hno zjg3Uo8kW8Zh3s#yV!&JoZbz~@wFL3o)zQHGKf$oYkbgG_AHi5W_q|7fhJqiFkPE)+ zFK?S$^!kT3k3E}54HTNScjG^e_QPF9RdB5l!Oj^>+1Fi X;tuwsV~{H8yfkNThYFl zh(ADmljyDyFsg5&E;~E-LhvMT*w-&HWC1iW?Pcs$UT;v;?cmLhfde%IE0uYHeiU|6 z1}RJ{F*6%xmE++^SgOS`Vh~CZDz%RA%Cr{bG-DUg^w`q8ZV=$i=Kpy+r+Q;e5J`aQ z8~b&HmEGi-=Or46lyWB1dQj7Pj2Gi}+CxfiP%Z>ru@WRUYDQq(W|wbQQaVGy-{7lo zk1{Lw_d3=$!k-O(iPJ%A>A6o!o`AgckBUGB+cgx-KfA+FtjdLVA|9>|oIE8Yd%>2# zjNXy05}M16U(7$-{2tJID@2j6`8(^h?e|ij5e!)oprBB0`r65>!n1%K5c8+8nWT(f zhoz86yol6uE*#gJQn)aM;p1mVJgyljhIndCPTk*p0VerESa{Gj5#m59Biuuk{ms+f zUVxfnNTdTOUm=e~(SPRWzdKeDNmOzd)Pc+6A|1w}|K1aIe*D@ViDql30T8bJal<*- zOdpc3-5yb@lnvD&R^WuSHpu6Z9r>FcCMLe&)8EpNkT91vmsue@J1Gh)eE>~hw>uFW z=_%aws?8IUIB@32E`9*Hn};^iO8it#hqeUdl2%TMMv@0@{))CLSBm<{6v<(0(dR@? zkFTt?_?*crR3I6UD7RXlU%g-IS34?S5i;m_7t?#WcXcE!VJ>Cf({&Rq(iy;)uq4^T zCh4gTqa}G!5TjEuQmR{WPDGu?hQSMzSC)4``l)`?IaS|K_7miOfW>4o%JZIzg|v2n zCfIKr5MMuiVYR%Hg9JM&qgF1=uK%W(P6Y%kj*KDMB-gO1tWsK#es9Kc8**KUXYE#G z@z4=Z5g`Bm%T+iJWMHqNN|~r|$2a|R{vo^pN8}a1TcVtDL!*;P=1*IJA3?wxJ2oz3 zs_ {fz%gA zJIx#3fN>!u?MFiKjceSL-c*qnO#M1hejNf7{w4*KnYFa@MFbznRpN$Q{>cis!eq|_ zATyceOGeJGM|5xeh18^r>lRYav_4a4`%gXKjG1qe8UO0N48Qkl+E0fF)?LNF%2rz1 zNP^mql@p(YVaAyk%2ac-p4BT`MyM21H0u{3>_wVH$~-=Jj&QTs6b^I03T#XiSFB9V zH6 C_ z5;-SkCbpR32Gu%UqE}axEt7w4q(Ng9H&vM$IS>RVM}l~j>D)Vh+p_!m?OTqo)yD0g z9 vjN|cvhzO z*3WxnPtoJtCAD;QWS8=vXIuh_+y8ph)PZ |gLZ>K|CaS7 z7f`t`uz17B(H^}1nw88*%iFjmhY@(-`YXm!BT0I;&){~%Dpm2a&;Se5ayBawfWC6^ zF!5H^t?B01K^VV+N9NyCHp!khJETRvDgIhfR1 ;(R>bbB>DV4Q|vZ< zzEqWL_ECjj-OEzo&u`rCt2xQETWZd``#TsS-IEDqN=iKR`|53j3MO}JkFTI(2Hx%* zN+sEW8`5P?og}+TaG;r% z_WZzIem1eJ)YRGi;-)rQVj m;BBkSO=ed>LkIEQ_|ft+ZNavLX+ iebJ{V`>$BW5FM`+M?h zS>+1HV#y$LxK<4z642K3I-2)BEyc%s@ ?xuE1i-A0K&65$nlQ#*w+*+iJ!*;Nma7+rj$K&+3Td46)8dy4JvK+iTwu1y z(}(jIQg4Mt1;}HVV~?)EL+<1$BvABF@;Noa#6Y=P{>C)NC&a&KW9Pb-FaJbOn~5?N zjb=pH72+Y{*UB%cZdAVo;^F;beb4khJ> Kl+|_h3}Uo2p2idsk61M$~w?GXE>=N54-QeXW>_ek}YJvYY*O* z_{%RbwalgkKBZ5DVrbPHb&z>kuIxDbSsYOc%}DvM@rvS~J&lvnJ4rhCXB7B`ui)k} zfXl(scGjfuNMVF9>-- $aeOtPR< zW|Akxo+Xc~jZi@n_5phzUfOz%ts|z0YDK}P?qhVuN&ZyPqrnlOdY00pY#|yMLNuy; zQlppL`5~(cvr*psk381eJ3lvWXHywsYANL>4~>|$-hUCaOj{R8>lNgUt5be+@$PV> z;L>AMdim~P$fZ|=xEsA?L56pGkDm@BiUwob`zcAK?F>ta+0NH$e61jM(H9npP+s}9 zC@<>pC(KQ$!sPumYrUO)GihN2AJ9rh dhVbL{YN;NERwTQM* zyOF<4%_Dl`S24E!L0v~c>L~x?krZd2cPNju)Kp;^ zMW^cU^x&rW^`XzF`d+kPI(hJu>T4*Rq&9bb&`$`%&A(nZQEvWLi?{TZPg@UN65Rq; z $$grpOp6ze7 vt(dnlqX>+D z1o%DMUh1|m`T2XvP$J*LpSRRx+*bR*sMOJyLllEwa>BxvFNW)}Birm!`EKX2%pi$I zs{Cyz0r??-Vl}+6$|@vCCBebD;f*ZuV*vpDLd{I2!z0I?gd3+j6bUmUvXq9*w5H-d zTB!T(5=ZK5_7Z#<_*hW!@Bl8u*nR9^{yVxSXq gM=Wz z`8>Zr-gxePPoHzoeLpusOGBBMfR+FN01&IZP|(3VcQDsaFfQi4hEu5l06+jL3NSrS ztOH}htVO-%hmN7wpf-~bjba=!?UR1e_Kr<2D!q$aUH8pb48R6A_OB=@oXv3!k<7UX z0`OVQfmH*g0wqlG(`Tc~%1;Db%x79v97dfJ{ZDZUDd&%}j{WormYl+t5UjS(1Wo 4`I?Y}Ku#A*t;d6hkT<5U^Ot8S!n-7i9 zZY+RHbN CltHp{YwuOdxwt|yJ_SHfr6-zBQtMIwIdIe?RS$n~PNi3y zYBn6Kd2CB)9+Q_@Xg}h@7^SsJq^U1qD3O@d5*mTB^fX|%@9rVDUmu2#8n+&Q=c!{L z1qJ7wmV`OBp#>L0!ri(=(#I 8*Yk^Rj5G!x*7 zyOaI<8Q_go-H-Ll49AT66oL1ss4tF3JNO!>(Rt+D;FEK8g3IJ!&yT&oN9_}Q1q`vU zpmsP~Znj0#lvl?(o!PMK4@(W~^DF^R)F!Ichf*)Mn3zD0Bu9MuhhLRR1juRP&guEA zMG%21UiQT+4 cN!3O>JMP7^Le_nkkAX{)rr z>YqZ&(vj;CIuX )1)(kCmer14lallN>*dDa`QVn?+eid6D$}fm zA<>zc|FsM0aqT5IQq2+*0=k}Rw%uiTBqz6F8$P%)1C(j%$$qrj-dh)WMpV7k0zujX zvqoi)zw;iIDjrN*Jp&4Q$|PQV22(~3q{3vux6e9*)3X~QbJqmNc)-_x`7cG3sdJnz z|EyHKH+1b$k_FR>e5Sat&Wc}8PwOhTXjPw`YAFXP>$|`EXp{d wq<<@2bwNq&AoUNxVt5zuVldSjQ zyX0P$JriTjzzOijlAe^|^2CyA{Y@jiB{BL5BD5hvn$xlBFyf4b-pw;-26hkv*{O}r z4?2y^`7Z@~UJR|>{pxB7z2K5vH;`f4_3Jd1w;LAKmWE{>I~+)-?O%Jxa=q=E$x?Rs zkb>5hl^B8#4fZY2xwjQgP_Z8Yj@m0N;C8P%EV7GiOoHY&F@-ypqrU_7vZ;7xYg y*WS3 z-GAy`nZj`Rg5_O;E7UH!({MY*#^zvxprdNPQX93r<}U(n3Bw)Q-+#q#!h6j65XTWa zveqgn8a*28KG*cKE^=Ghp+LHx5av)a(^2ujIEKTG4;$R3xF+(AG*9vlbuBfWL2o4~ zrt;3;Ya9L9Ap@l0Ia2ub4?L nM2mD-+jz4(pY9nJ* z6e&z~-gf1*#pcY&+#-xGqC<1~_GtBfE}eR8B)VjrYr)D=Zj6hI$?^{zf_?;esi!R! z%xvY|tk?U&MF?b_SoV{Y^-l!H^;TpC%FK>#cm2W3X2Zj>GJedhp_&=GL;2C+GB#_N zo_-NqLa|FrWRgt=lGQ0)zbN_Nr|z;OO4rgNkPso5q55Uss@#QpNYg}}uak{vMMWhQ z7{*>|A_Mm$e!-Jd_#!-WhfD_IwrvbYgug6*{mMmm1si9vhtT5{&y*I-izm|5S^O{O z9pCvNW^t(m4E2vtRF7EQAM=}QRMv t4XG*xH^Ca%3tsDJaeWKHhaVbI<9`r zGouB=Ni95FO9*vC)w(ECpmf@cvnMh|%g*?~2<1vWrVS}4gXQni^-FKWTJOZIetj%8 z+)5*Lhl12K9gl07(fYgZwKLmW0^TLWLEQd3dEEB^<|4@OJf=;hUuE9Bskmu|+J-Xb z$7j6a`#5x&<1m7&;CRK`EPCU4#7Sx*QZl#V{s@9}DqV7$&Q&Dv>nfN0Fu`B2-drj} z9J(j6O3XUC#$e)jj9~7BEq-ttHR@Ywb^5ZPrUf3LvbVn1g}~NZ6Q{PD`>{mm|D=0+ z@&U1*lLqX|j-s69x( f;S|S96B_jZ+VQ3!#Q<2%C3)Mt|$% z8}cVHOh9A#QUH^Yh&v!;BwHdO&zDfi-T$!tZ#BYJ(nR?eT=TFppkPUU 5!BA=YH3KswD!J(?U#qMd*qVX-A76oPwT~F>|N4DH-a3C2nPS) zCpTE|nAEP}ak@zd=yApuGP_nOG*^(OeuKZq@#jm<_IQyQ14@vilLDV*`^@ic;25c? z4SZ(~v?t`;DaG#gLqO-P%kU4M^v)(^alW3}bIbKmZ!bwZj^r374n_pEOI}aL@53+n zt3Q#F@`e;zx<*vPl&*%MI?xHBBm!3AVAC_-eF`p#DVy}Rl?HtUithed#n`X7;=5^# zve+$z&}hHBo>l($o=#`Vas0@Uf|bzxYFhg6ny1ntY ub!zVr=ec`Gp7HUYx~wDNkf& zG~O>s_d>Ai<7V`1_GpHG 7fy0Ifb)DJ;sM!x|cZUNwtaA7)iL}0&&sA zYmmCFsxqfyIchv;=PBD4B2Im*lRMe6+}==~F4vG@ZL4;NzU-)PU+7IIGhb*2*R+o` zKueN&vU`;eot+siK;jB?@jHYjyhVo}E5M(_jjW-m2A^IITgbnPMUGn2rR$cUd1W#g z#={fD`WtXyl@ J`Eh~bg7*$(;}Z0)BP-gYRT z%e{!dYY>7}N~v4AE)#$amc3*H76SDeMbi?fBOPYx&zp_?%abICz-}^CqG`2#PPM<# z@9sV|JcVuZcv_HN+wS_OXXQ=-xyMOG9C 4gpz zi@MHbnr#Rj9>p=4)+9D2Up}eC0ZLaD>O2J1R8`7No`(RC0b8~uR3{xjQ&c*w;a; ?|li6~x8_wx2a^{ra99i0f&*WL75b1y2t;NM7_|{z& zGPTFI^nHfh*1i-L@SN=NQrkJoZ5zo}K`XM}Echnh++~|=&$|<}N?xApJS=?RdqH5K zKGr-k*?LmnV;Wc@>BZ6e^v)BGfO|ki@2@N!&I)j_M$`Y!sQ2E=H!J^@;K9Xa0kP}* zph+LCXIZF@MV)_Nh(7Bj!#(E7avK`-5KLGaq(1yxLSkuQX$Y!v{p~eC#~-`JwiA41 z*T_S?N6UE4(^^>BQ_HYosWN6_yJ1;4a0NXRsLv^}Pg-@z`;p_2gBBb2KdM%mk*E^8 zI ={{1TuByGgCslT?5FxB(F0uX-6kM{cLV>h}pgH(#O$_L)bPVu-Az272E^yB3 zeHe-N`yK$&)cXB%G5!;KsjXQ^Qa?gk{_`f5tbZrBGIhleA G~m!6)+7 zjB>Glv=Ml9`tfhKE8&Be)3a(V`rb-DOnY%7bNZWT{m1K8rT16#Yox*4nlNAonG&JY znJ14Nn6l7_vQsph&HkX<&41lOc|lT?a9O`BIHNR%GH%0$#QxHb^zlD8Vcq$imDG{* zoIWrj+7UuSAhR7_kh?y_2%ivSc{*_MXYi5+J3K27K7x?yR}W$*JGu8lb|;6zq!*>D z50}$(n!dk$0_v67Z}P4Slf uuWi?j$fM*JDGYQ#_!?YM?uxs`LKlyY32Jf&B^e8Pet;o}oxd zn50IL+8eun)D*r-Bt7ap4XC616%;`2a} r3qpCVf9akdo%c{Lk#5BdFxqR}Z{u@H3 zy~>5m4A7}S2kG>1a(*Q|kL{|^MVG9J+4e616^?Y R#)Rd@&ts{z1mhKVG4a4o^q922}-MW<-J15@e@?mfT)`%RgC{ z# *=0!kSgQU%HqthM#6w-7utXXRueell)hyqCr3iG{j{41`fzgs#<1HrLV0( zN2!*t_2~J&@M~(=%}*C`(RX~MGj_wS!CzvR*30y@Koa wLyzJE3B0U2?qv0Ms>D^+oWH3s7-RIf7F~cUoyN{G@2NSiH=F*1ltu6%4GvICR zPjIIfZvWbYtApwfCVIdwT9rzBPaiyr^hiz7`}=|AliFks(xA|+$5%-0qpcM5)knlA zt2F!M@rqVtdl}d(L3e(*&UaeVd-`)*VBI$;*A)@z$Tb36LO~CbMu{~#=NQbFO|mYD zt;)_rv!=u>Cgn(dT=jZ02_vtMbg}S-VKrxNzB9-Y^(8J7VOkG+Ar8wU1D#nGIL0l7 z#~4_VxjdIyt$cpZoZ;G(tAcMo_k&1QZb3f^5_VRFuye7>gw#|J0OOg_&87cAiUVaQ zwYX}|ziK9nV9*4WFdc+GviMJ=DNZMJOk`ZvoC)z+1a9#Hk`@5)P$Hoy9mUFPc*K&M z^f&3lomqfWiO?%nJGT9ms9@R^l6-^@2+k$Wfj|amfCz#F{Yt=1Vbmz;QY8YXpR<3( zlh+nw@)kw>0w6Mmr7p7w@Ck@ZBB~#uINPF_%cR8z>}lS}R+`(v?PLrrj_@`cRkgi8 z4Aq$n%~R9h#dDrsr&xaea_Zl%!ZcR8R)-x(&nbekyM68 CH!$G*^CD|DU_rtGT=!>*l1C55}`OLrB?Suoy`h(gC+xlebL2$q7qhb|57Nq3siu zmtyRe){fVf_IUSs_eWz~H$M0f9!ovT08U^W dOYHUC9q%x_qyfnLVr1G=s!SwFJ*vQmoaA3)r#zp?wWo87m) zn0drn|FW5LuyIyaD0kqdS5=ME|9%z_5dDkkwc)rhpg Swd%RpsZBTtzVoA_zynG|P)fI599`4pHfRv$*k8Z7zn#XKV=sHrZ=2*@L?Jt~| zt~abYn7b>2=ijO=6pd=W)@Z2b1GaBJ(tX_OhR1Bek4QqX0}<&G&(~c}sZYh7nGpX$ zjm4U?dmCuOPiA`c^y1jABc72j-6*!+=XXzM)ID_?0G13oK=v%q-}=?lJ$^B O6!;~jf4_C`1yJJZn96kv?j`0JeQLg`z@oWLlY7&%pRm+3QWdN2 z rto+iVG--+S6*#24s-DU9;YE Q``AY$G?_@%~OgW2i{P!VE-;}%5NC*4XXM*uTba~$y}q^ D!H2IJ)dtv0l)}HTYjH*KySK)8;fh7(=@{v=QUUTw=C1J_NbR2|&P_%dVnC<&e zt&8B*$enQ9K$Go=nc6M?ZM{vSW*V~TB?X4+(@#&lW%^USzFt@O&0XK^rF@9qE|xj9 zm=i$aa_3~Wy)8WpY%@Ca GRI~EK=?5LMc{_+nLgVBDINDiL| zW8hr6SH-~-ei*EDp;{x8I{qyQJ!Wtx?voshNeV-;YR;K~S&qmc$WW3}4oXnBJO=Y* zNcpS+0n-PT;nTKklIVDz6`|yNIolim!R{#e4AJZF4D@=w>cp?Wv}AYb?@v7kd3{+h z4QN?R$18{Oewm-Vd>$I@#P!@_&aZ!u?|y3Uif?e1g^YBGR{KePfC1F*XR=%Oo0ktZ zb3X?0PwfE`Bv?J3r&3mY^4g;G;WAhtcCwOOeRs|&>fiFGHN;6^n0&=|l(AIRzWyyW zU?eOibH|Ns7n`2i{W}&ROdcrK)Ufe&Q&di;F*;*fKVKA{cr`tJD*88v0486?($VlA zoje=s$I9|hbmC%ySm8(P@YHR&G00v}wRq5ewV6>C1XbTb;G|+S-e_i(nJ;PZylhJW z<3-4o__kCIsB;old Hq;SgKWnNX&-7Zgb%D|!GL4*g7FX#3KQR7xb-yT zAbVvDZ%G?wDA*1orHt5KK!^lOzk(bS;bd7A0a)H+45!RMFPuz;8Usx6e0V{%m{`H~ zFF(jnl7~nzML-{>*Du=dK!Q1h*h2HZ#tAHgga_oknoE}Zmw7mtVJ_JOW~A&_4A3h= zh^XZT>jh%;CWtExXBvBoNuXgl8S>W8s3pvNgJJYbDaR1ZbY+@|`GV_V9H9xu)Si zf#rKiW*K3!LMb76<7h4eoIouMMJTX z8Cx}AtI94oao*Q~>snLvkQpHgcw z!(@3d2G-|2vBtp~#&8tI=G_7X8enLrkts=3AR$Z?e-SmMQGo3KsZD60o0?3Hlr6!0 zDj%Yogb!TBup*|`9A^UuW8?_wi7BQtL3n|Vnp(_vb`ty5pSVH{=?{yD1;!bvj@B=6 z-2r*+oeSjZ3lx-OB;gW)YE)$5v{$FM+!ABB>5iIXA|)*N`9T d~jx(TCOv^Q~tKYg_9d;Cw~qi%Y`OfvKZo|1%rDm$xJ zT4-X6X2~gK?*$kj@6M2D5%rW}A$gF86VH^ks(*|js`d#7)*^*y&F70Sa;5iRdzx8& zygnW(RRy^*p0{c@qUukMa_h7*DbYdW8RoV#3+v=0oY$&GKI6M#@%%^A@2Y7HYo&vD z>9ZIPSZl@0^{{Q)tsy7#Ue*P1+}KO~!;7{BWAvuks4Aj8(GTZ*4IttGIW3Kom1X>6 z%r-xDopQY{3qk$oYp`zL5W!BNIXl%?HeT5Z{0tA<3Q+L*Jc3V!<67>&b?%KJ81R$& zSIL)AkezvRkKV=tly>#eTM8jC2CATjpw+uv|2&~>vf#gwHCpFtDka4lWBG8&NA#`9 zvLwkvw=XoGn}EKS-45c`rS3;Ud`)!xG!uC#^5Q`Y#CW=xL~-?Ywof_`J=OF_Kh|Gu zq$tE_phEd|s+uZ92*7fj)<_fTMToWZbN^v&3MnWf2S`O!-4w58-ITw^?;K1|Wv0mm z1gyB)U*0@sGRW7vk!9PyYr>m+hOzfQ4D>%VTqW<}dG<~aKm#7Z!p#J~?h}S~M*9@z zkm7dq!4th78J#CFJ+iCKZIkqU!ua<0N?Y^$1RZHvdle&r>J93ib}a$UE}HDsOf; zAi+0qlY{LP=AB486Zbh8I_!Y GvxmO)OV~& literal 0 HcmV?d00001 diff --git a/static/tabbar/home.png b/static/tabbar/home.png new file mode 100644 index 0000000000000000000000000000000000000000..ceee161c1812135748b517efb72907c6b2644a09 GIT binary patch literal 7657 zcmZu$cQ{<%(_buBi$z3&un}EE^e(G+!dLG#dR@I+ogm5*ebuOm=sg4xz4uP^wo0@m zew*k0_x A`BHgJh7|5%Vk1lfz}>3{5{WpJK)O*aqPCvlL^NG zthuA^d$IIkk^VXY2Tp_5$qOK?7q(d*Gj_E$iEA7iTbX!7fYVpd(kw?TeS$rIpGh zx(G)##0*+6zk~p-!O6KkpIUbCO#-%b9e02us*DT6SL*`Ix3a3Bq!L0hFq|FekE8AB zbVhk%MprVjRk5afVE@jvm`!Ek*&l6$L6r;?w4ik1usg$v7Fz9VHgd8V(fE9_TXN4k zShGT3ZWv!vrc@`J{EBnPjqU|dvBxomip6cj{F*x*Bb>I$o<+%xK%;QC$3a|$-d8k`hl zDb-q#GIlC70A+ssvR_|md>iQW8k=^JA*BJ><8Zw%UM71h>qH3*M`}Ygj8g}j(fN7n zW?;G^18>T}K$QvQid1C{A}|=<0Jz9!hn4sXS+h2|2l?6h#(mGLpvulW`{;l0WO4j- zKLW`q2D}bBSHZr;%|c;~^eX{3(f30+H*M$rR?lYiXNo=|kH$lr;l{tw!} ;@hx=6CrMRv>2MaB3BfcM=P}D8z$6Q0lhJ&m8iaQ)ZWAWd_ z9y|ic{TwSGB129g#gg1q_0a08E$zwq9TT>gag`LYbt_szz5D4UH}|h6NgqPMsglt= zxazA`syldTz7jig6l7rg>*u2aemK^FU))IT7JOctK6T{yWr(x!CqPQ`KIA+0tijiU zAb7*dOpoE1gMRBDv~icEzdQ$b+S&>A##}PudqAng=zusDPR1z^HJQJ~9sE69(NA$m zL`1C(%vbPwbZhCpUTNDIAo7MGiN9wI=Na-FlW4GVee70EN2Mc;{OKEix%zu ^J< -1d>^Y0dzB}P!eZnO_i6!pU)9)caH}R3|tCpEd7vnUAN5@`%aTa z;vyfTZi#9luU3cqlV+sGm=i*cy1bfhs?l#(5+vH0lD>vhxxd+kHww_)_FWb0V%css zkDCf}C|nTq3>*nhife|}OqGM-k-G-Wg!{NxQ8J%M$Hi1qW&wK&9pq|6lRkkoqa(|q z)Od`>bsev^A5PXG=c-}@@5sj!=F`)nso(;j)-UM|qglsBkXx@X)oz^!iac;jdx0=Z zWk~*!lFncAN+4sgVN_b*T_AOehtiOUCYuRp0or&;eHkp3{x%Ps+9nYS+P*O;j{2JY z-KBFVQ(L+CZq+n!ulHrshT};2glx;YQH7Ge!39Y2;81b-RgknaXLM${zIn)QEGG{l zS7OjFUyXvM+^d&Tw{i9Bc Y9jz4Q|XM>gIr9>99gF+=T_>2ymSo z={BJ=7q%;~POjJ1>*}0#r$4}&sGxgXp;B6@pWEgIDv+(~VOm2R&VIp0;wB;Q6K3uO zJe%N<0<~mxY<2!DrbV*3lqgxXf@}#wR)=BPy7J6*SdvVl53mb2F>J8~XzlxQ=WdD7 ze*I(NVUVJ~;R{;?-FE(#zYvm4tk2IGvF!F(Jlf!WoekA-th7%%kFbx2sq6uDBB<*` z_rPgJOZ;q)M}q8 wkgHSjColW2#rB)MM>&pinh&q~H8j_LWd- zlLQBP2~ _8FR6FO }=aaCqOVsXt(>SlQ)c_l)*DbYcdHqytVY4E^s4b6{m~9-Y??#%njLU zwMDO4$VJDQU@1X>li?Onqv0(IErJEC?fZx+bxb9^wEb#+qDn2E5Q1jkqwAqRsp~Es zPl@YgQo87^EHavT=$F1I)Qc})#9q7ZjA^ms$jXWU28zTYTlDWrBCp>-919Cb!DXWy z+v+0s7n8H)W1ltg@ta311C^Xf^+;LnTAW4V{%G1gcJWY&4MWBNxg11318f^P_>S8& z$A{RbJ{wV{)Dg>k;9xaS!o7s^|J|hZJo!|tB?3nVY!AQaOnm&j%LQ0LkLs#$29^H$ zW^XUn*B1No%jQjx$+#waH7CR0gcD`;FYnbC1~k>jviFR-a<<)dl5$BH>NTo@kU!Q~ zJ$$^@AN{i3)SJP{o@VUfST&$fitl)0r^qSEIp{}kDoo|xbE-u-hc`*O0D3x{w6Iz> zmd^J)7lGak(Rqds`VN$(XBavs(3}3Hkfhr^U6hQ}A4JQ1&-0Bnz9-zdrsz^d@V{&| z?!JcI4G2`^7mI$@o0&*P(09wR`h&yNJ3sH1h$niM@DwK?eFudB_e!Xq!Ao|(57Dpx z&~EOs{m0Cyo6of;a{c$?^ dcpRHbszKxkND0R59vk?15>&3SHX z#eVh>7_hb4nT@hiYyP?XxQ)DX{Vi9Ew&s~~kq~VuGcP}IYYgoh;$z9rQuz8MoL{UR zRh68gdj+d3&3Omm(o>2EAPmwqykfsr&EzKxco^s7EKVkb^9b9VjoJI9 vFXI hSJ=?BKh z0k?XzNUfxsz)|i;T pLi(Otai6xk+TX97@;R@R)BjG{?0)YD6~X-)P;w8Oga@~Z~S&`Ej><9e|GCFfiH zQDxBF@FY;_;#6`WsmyA}1&HeVcCHT7Nv-o0E)0A!=u8CP$KBC+G_9^R6_%(S-Ey;L zcd!O$sLa&aoR7dQvi=D`*5Ipv_G%ovatNGIihTcE_3f&t7!GjRzPd;B8+ uSj6b zn0@Pku9ZilnhZPLVCH*Ufg9h++?sct5xMRL#amNADlTnzQ<4IFn{%gPS2y>!u-dlj z(?)9N|6b4k><{Qoxc3YuF`O|c5%Te%Yprx;qnwi$%%<`b&rmL7OhC4n=dGdN ^!es#C930%mvsTs4oKT)M2xerPTQ~BkV?3Ed9hz|Ut1EN2!$#WWWttnZtuU$ zg4TG+t~H}TcQ>HQi>5F6t`=>NYKsQmlcCy{2D@s (uKTO=psTfi;e &T!J0+0#tpT8!?>2=BlLSh#lJB zyOEsZHP?U-4sMHKAE% BC9yG1o9*jA~Uy yP7b-xoVRzQR)NatLm#I8u)SWM}+B5 za##o^A=2sHpU_E|IBQu`GUQfed0BDn3aXBo3@#L}j#dK0HQ1rhaNl=bbfW|J8W9rX z<0~MQ3?6IWet`sYuE*`IQT$jzIbrg_1RbjCoN*Y8Ao(8_z@L@HVC!mGd6S_)T-HY> zL1FUzj=ETD;Gr=0R#P6Vmk8)%gF`lY4;nWg)LVB;YGdWo7x@c0_#|PGfeAkae-5*{ z6mg!>Qsog?FC*okDJ|V#vt%` {iz4dE+)o;yA2ih{@Jfke7F3HZtmoY<3r{Ir$e36s8wG;jR{Lp zE@X@td!=PsVCcOS-<%g0^IojoWXZJAu}v*-ICEqVkl9l4bc0lEk(MHRUcgmP05?>R zYz_1kN9J>KOR?6<{r-2IFPU1FYzS3yKEvwoae%kcl!)~oaRJPtFrOqx0_=S-iuPO{ z>iQJGO2hpgOh0HaA~d7VugzpT;_AFv7Ee^(5S{ {hG6}jz&qJnmYX*Xjx?*f`6?bD>_3pPoll9tulc}E zQRs5tB#D1vu~sC8{dvcybvk>;AD^Q~wE})>KHJvWG-#>wC=%@2EP7cV>fABhs`(5M z&9Yx2>RsB=NRY`-8}W9q3)iKJrpU@TJ^#_5w xq<91phn9jYx`i_wj&vj z^olf=nvqq#STEWYP #}Z;&flxO S%SXoYCOt=plU!etpF5p%v=# z_X2-$B;+F$lj;8Ml$r}-mHI@#rys0on1W6|ilri|L;+E3DkJWX{rpJ$PqNMPN-z*b zi{0q7Doc7}w)DBL%?|7DxDOW)WV+HKexIBx5f#w%S}&v6usEeQvi+nd=D*eFKPNHw z^1M1FLBKHSWJjogF%C{f4nL!XH3^?X<-TT!5~(`CbXu=A-hsE;e~WO$n0li-TqsL1 zm>Q6P2bjg+PNrcyp4~TWq F7Dspmedp&RH(K(i5crY>28og>s_ZTc=@a{Dhj3-!$17a~e_lCOsZLqm;+ z8iJf^1t1?zu6Vh2RIcWRXHs&?WTCUlh1Wj5;G~inS9cZ(xvy(Ub8@gm{sofbjx{*Z z%5R^6({PV|Gf9 wC|asfSFm0*YE(bn6nc7CY5&+(*=pckvGVQU?9N2!+|l8?_VsqCr-z&V!j3 z7M%C>m-ts%2az@P_Rekefp2Hl`+ic>a3 ny0MMulVXCqm&3Y33cOZ8##JId7`y zQ)3oP%S$&QH9n{n(nBR9#w5dQH<1eh!cvFzI_OP96K&-}Y<8a5{xuu>)A9Z{&`B69 zV($K}Nrp&({TWCcZ|AZipmTE|K{)=qe40XcI|I1E25g@QO^8;Iz-|?EU>F4lbm%|( z;vjZ(<&6s~7K}=dI3Em)%fcciuN&oo(_2T~_|BUOe^{Qh+4)N9qVgw=c6Yw@HutAe zeSHw4JM|=cy*7jEH|xOgKkezToH9RtI^0M)22#Y_Y t04zSnxEHSGiT9H zcm&h|=Z=;lDM!!_?+S Xl<~(J{=BxXJrvmS>qd5T1oqLc326=_@j?vV z@{9_MoI1k18EzRuOo8zU+q_-rGxmt1<^W;};iu&I(@aFza3~2-NTjXc@Hbk{9LwX`}0Mvadmmjd^A#;!) uPKBNk9+tH02za2o^fjQ)ajaLD8Uy)599sIks}3Io rJ6|D3 3gc zIWEu!mlB0O1sSB9lre%p*q)f_Djdc#22dR#=I<3BsoLSt=NPv+04SD&u&e$FV*hP9 z&LK64QJK$4oc(XnKgRNw|FRWnFy__$DZNf%$EZ`bujW?b3F;}-|A(eCXoI7H7(T`~ zv0zCE9fp3o#;%DQs(^7^IqX6Z8E``q3Nj%5f+^>0$uM%BU~$>whWcU1GhxY7WI%&( z%nr$R#u-Q=|E>OmWb`zMf<`$!fqPwJL5^8yFv4rl@|6d!80zyNKs35v4if=~f5{Fo zCsZ1FUH3PtE8Ngbj42LMjFiC88B7E?J-;l_2bacRL^I21N`h_wMZk>ts^)M(oA|#* zgZ$eV#Pe7TSz6R&$(a-*`e B1;Xu_SDf3Hhi8XV^GX+o!v{iU-~-YRr*#1@?YCiMh_ygJWy`{R9es{45lB z#iptK9|@V*nObqe?d9hp-z?0s&P_!e4jq4<{uiYs=JGkTtH-(wFLoErrmo=~ms;`c zW%H^4Wo4Zp4NY2x)nE~}hSEA5-USQ9?fy7oj-&K|x=S+oleww5S!7jrVZ=dqLwsQl zsaOw_-m|Df;9x*J;6yz$FotPY1R3D4{Gjy^I93}Um-5>@&r)Il-@!E5F?R6@{avj% zM|$;(*NpyjQ?*3rWc_iiFatKz^L4|jsqbvd)+{Gy9X-UY^J#PBSVpThRL&n%B`M$( zLAbaWc$yZlybzv9;Ji=e%lhD`N%ETmoer{9)I5soc@4L=UKDywuFnlp6qCfs6JHcl znOw`dYtMrbl1r$|m|h;j5gs-J4b2qfIawZ}()03sgRl=rQuW$XrJNvYvvq@?Vx|=V zv?0#xN5L@XzQ;!K@BO@jW@{{07GFO~rG??Gk~|-}l;~_;o^*$NIzYQ3cRo=hAFC{a z`2aPeH6|!W*wESRYO68e4f%VV>KHR~O omUCq5{t9%Ml ^?i i_Uc<=26+E&XE=bY)d+#frbrFU3_wv M&nGhi?rix&pC|e_-h}9I!B5IgQDkYIA zB_K#$0I@_C0YR~dA{GM3QmH#yMLdNANEJj8gkF34r|0y?%$zs(y?ej=-S6I)x dl;sKZG7JF%IWg;VsnYS zFs;x;%@eG*B=yXdm0hw(#hSS1`}MjEizhDr`RU~Jt bu@u8dJX+-3BK@S@n)&a-(0|Y#k3_JMd-N}Rj0Tp }<%$pOgeU3F780E8p^HQA1DA};533dk@mw3C& zsTN(MNIMjaIV0zLQwiTGl$`kz!zYfW|6vU1dgsaCe8i))%}G-=PAFq|5Q%6Cd9sTs z>B``rF`%?7#~gx_5qfh}i?W*_rKX7=mJ8(6;`7p`0$fpQtzDWqw^b~s_(AIJCP16p zz)2-QsPNBGz~O(4k7pREj|~q~;lxd%qs9~`dARZi yrDWZ3QXzEFskj%qI8iC|j>vPT(x`6al9MCK^gaLlk_5vC@Th&e zFudhqdF)RRfYUYJ1A8Bo>!=}sY_f6$m~b$kW6Pt&&&Id?u}Hvf6&d?kvF_|g2d4+U zM+V0}Fnf`5d28Kpy4+etb#|TzP7Ka&I}>7In6XW9+~Lu<`+$Xt3S4OC9Bx2~OV;}E zlnBijh35s}1ov!uShrJ@9?<)wKeG@LKOa!h1Y$BdBJl)4c%~Ue|6>do$n*{5_-b~A zr30Rg;kUCvQ@(rW?8`*xBiyQbLzKzXtVz5ZKWbnZY;C10l2gg8OTD1jsdrLSF$jEe zxsscX(7k)Z^F7EYmmewB !M_$ z&&ZOL7L<6)sljg|U-AgD57(9jWFz$L;f_9Q$eP1$t#E+ov60>jFub_Cx= XY{1QP_TbIe0AEK?i}yl-y5e7O`)5G&g(k7p^EXwjx#-j^UnL z%A(%E=FTooDu=Y(Q_Ih9?+~!}^e?)uM43Zn&AY3h!@imIeBOFFb!u=~&rS@_c_^QZ zG`Khz%=DzR Cbwce3@bJshKtDA?YgR9Ly%k#cL#s3mH;PwiYhT+2uxnd&)(Yj6 zM^s?Y5rl5_clgTyx>VS9Uxr`f_?Dr`ZlJ#YL_No22p!@0c)AO6yR@*e-RfUB$zIGM zhiki+0nCUcMY=*tMID?PpSU^tcJy_ptEj)wy757 <~OrIa1>o7(>D{aW+n?Vz?knCU0;k7%Z;wI6#$ko#SKUJ zThtqu5DV--Vke5gmEY9YOX4QiqRh~W%KW7;3mihm_G9?HNa?yTAb(4J|0J|lr}q1& z_{||ooNKF-fTN5Hqgl~S{?GC(?(AqycRU-e`4tpcaZR}ow2{~LASMkaLwE}R^%fv0 z`@#cr-rb`rYW{|#l&gTL%(Bkn9O(ML>(Ikg$d$|W@nP%>e!p>_Ea9!J)+ONy`||w? z200g!>Xoe CR-tg9F0y4kY>DNJQF_4{pZ|=vfBSXWaB2M=4tL%I1^K|5M*X1>gk0v fxR7SQzlmlcFK@rQqbafUfIo=mI*F)E7|Q$&E|s|> literal 0 HcmV?d00001 diff --git a/static/tabbar/statistics.png b/static/tabbar/statistics.png new file mode 100644 index 0000000000000000000000000000000000000000..da5b8890e586391200af8dfda466f6a4e12edd9c GIT binary patch literal 1729 zcmZuydpuNm6u)=eeC~ME%m~qbbVc4ot4I%XBgW(v!mJcEUX@f^dP(DMCbN;dN?sXM zDt3@an_gSOAhCL=ut}yAOWBedWlw$fv!BoIXaBhO+~4Dz^F8N$&$$v`Z+A^KeKiC@ zG(C8(ejw#v9$XdPWx?fA1W}Fma3uqFp+nuVn~j!FPYz#XIWxYVU~qm46A1Lp^aa`N z{L4Q#hh7}s=QipX|LU3a{adBO-0Kr#V>{ahm4jW%dS@(yv&$oQg%u`d5pq`Q)F!@& z5aeZU#8FD)#sDqDq-MN8;kH$?ximkvWluIjPBp43;-FN(hL8t!7`|;rj%Fq yCzNuHlPCBySwf4%EO%2bJ)oHrXMs`)H%E*Z??K6@t_@EBlRn%8*Ip?? z4#$k^CHY|ZC^ID;@75yZOVVC^9(p?kEZpcwO)x;I fbXTn5{BT7x*k3=@CeY%;FwP)y^VH0xuw>E2%5Hc{j zDfKSS66){Kt>B6X%W7f6NlaX3Dz`m4wV5X(^g=RYW K2ZaKDpL<};bBQ|#lh^KsTGw>G~89LH63gI=slm_AB*x{UN`gRkUc zw;j_E@^sP8H) ~MMYwD@ko(~R~?PJ|= zx2s}GCOFupJU;@Nu$irHp+)c%V-Zj0aOqH2od6TsjV{=~Px(OU^oispgvaU5QX2Jo z7|B~&6jxvDxVk1W-IsSvZ%^&`! sjJ_Ctb8YnokK)(c#4;QanS zYg+-GCP_%<5)fE`cx4|1cE#IsdI~}^GQ*GV!f;N7me!QnbP&y@)6UzVl&mYi$p_48 z5trA6GBCl#MMnyN6sFwx`dX+#d%pD!D64m8#sU_>Q?U R zc_u&?%<`6FB?K8b>ogPK-B7dhwt^t >@#JOcshr>rgz*KVXk_Zr<_o*5%r9OXe zGl-nhDY0NmXT#V;7Prp_^H^OT{R!N+wKFA5mhsk0C*DEPon1_gO}O+eMP$l?MJi;Z zL+|Hyh^W?}t`)W)Y5wADk5UK98@E(Jzs0Kz7cB2B+RGeenH(yGdftDoNQ68X+!U@{ z1?hc!rF$CC+9lhnlwasYmsa=NxQhsdh3+_vjBkn}Viz(n^Po$=y5p>V+ >yY5X4ET>1LbOBfcdoKkiX$rFgdk&T|KmP_SI|)JjtG#_|Q0b;l;bo zu0bER)61sUl|hFqtxvOsRyt=4U;luRiCbPfGxC7w62(B)gD7CNthIUm0fZEXZRZ6- zJ3N-Hc7Ybc-3|)jaG*8!%LwwU9~m8h;IA6~=>@wb IaXuaW4|OlPn&fm9%J=0ospx zPKI{Sc{V}Si41kTV^#+fuZBWeE>!Y?Gm_loO%QqDwy{hgBWJ$)BYt5GQFd?061p~` zRHr%_A-_BO$X|?*%>mZY>L^w1TXjYQr52ZLXnan*o(BJ)$;ma9nP=fc^~)bf1+n>b VWzyzp=p)!cJeGUAmM;sV{sPq}w#xtj literal 0 HcmV?d00001 diff --git a/store/user.js b/store/user.js new file mode 100644 index 0000000..20a4d99 --- /dev/null +++ b/store/user.js @@ -0,0 +1,47 @@ +import { defineStore } from 'pinia' + +export const useUserStore = defineStore('user', { + state: () => ({ + token: uni.getStorageSync('token') || '', + userInfo: uni.getStorageSync('userInfo') || null + }), + + getters: { + isLoggedIn: (state) => !!state.token, + username: (state) => state.userInfo?.username || '', + nickname: (state) => state.userInfo?.nickname || '' + }, + + actions: { + setToken(token) { + this.token = token + uni.setStorageSync('token', token) + }, + + setUserInfo(userInfo) { + this.userInfo = userInfo + uni.setStorageSync('userInfo', userInfo) + }, + + login(token, userInfo) { + this.setToken(token) + this.setUserInfo(userInfo) + }, + + logout() { + this.token = '' + this.userInfo = null + uni.removeStorageSync('token') + uni.removeStorageSync('userInfo') + } + } +}) + + + + + + + + + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9876c55 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "jsx": "preserve", + "moduleResolution": "node", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "types": ["@dcloudio/types"] + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], + "exclude": ["node_modules"] +} + + + + + + + + + diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..e7b25fd --- /dev/null +++ b/uni.scss @@ -0,0 +1,75 @@ +/** + * 这里是uni-app内置的常用样式变量 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #3c9cff; +$uni-color-success: #19be6b; +$uni-color-warning: #ff9900; +$uni-color-error: #fa3534; + +/* 文字基本颜色 */ +$uni-text-color: #333; // 基本色 +$uni-text-color-inverse: #fff; // 反色 +$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable: #c0c0c0; + +/* 背景颜色 */ +$uni-bg-color: #ffffff; +$uni-bg-color-grey: #f8f8f8; +$uni-bg-color-hover: #f1f1f1; // 点击状态颜色 +$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色 + +/* 边框颜色 */ +$uni-border-color: #c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm: 24rpx; +$uni-font-size-base: 28rpx; +$uni-font-size-lg: 32rpx; + +/* 图片尺寸 */ +$uni-img-size-sm: 40rpx; +$uni-img-size-base: 52rpx; +$uni-img-size-lg: 80rpx; + +/* Border Radius */ +$uni-border-radius-sm: 4rpx; +$uni-border-radius-base: 6rpx; +$uni-border-radius-lg: 12rpx; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 10rpx; +$uni-spacing-row-base: 20rpx; +$uni-spacing-row-lg: 30rpx; + +/* 垂直间距 */ +$uni-spacing-col-sm: 10rpx; +$uni-spacing-col-base: 20rpx; +$uni-spacing-col-lg: 30rpx; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2c405a; // 文章标题颜色 +$uni-font-size-title: 40rpx; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle: 36rpx; +$uni-color-paragraph: #3f536e; // 文章段落颜色 +$uni-font-size-paragraph: 30rpx; + + + + + + + + + diff --git a/uniCloud-alipay/database/db_init.json b/uniCloud-alipay/database/db_init.json new file mode 100644 index 0000000..ff60f6b --- /dev/null +++ b/uniCloud-alipay/database/db_init.json @@ -0,0 +1,427 @@ +// 在本文件中可配置云数据库初始化,数据格式见:https://uniapp.dcloud.io/uniCloud/cf-database?id=db_init +// 编写完毕后对本文件点右键,可按配置规则创建表和添加数据 +{ + "opendb-news-articles": { + "data": [{ + "user_id": 121375, + "user_name": "未来汽车日报", + "category_id": "223", + "title": "为什么自动驾驶诉讼不断?", + "content": "", + "excerpt": "没有永远的敌人,只有永远的利益。", + "article_status": 1, + "view_count": 32053, + "like_count": 4603, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 1204, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200410/v2_9c3331af67e64994aa97a27fffb1a380_img_png?x-oss-process=image/resize,m_mfit,w_520,h_300/crop,w_520,h_300,g_center", + "publish_date": "2020-04-11 17:07:48", + "publish_ip": "", + "last_modify_date": "2020-04-11 17:11:09", + "last_modify_ip": "", + "mode":1 + }, { + "user_id": 121374, + "user_name": "36氪深度服务", + "category_id": "0", + "title": "2020数字中国创新大赛-数字政府赛道21强出炉,四大赛题紧贴政府数字化发展需求", + "content": "", + "excerpt": "提升数字治理、建设“温暖渔政”——四大赛题助力政府解决治理难题", + "article_status": 1, + "view_count": 53855, + "like_count": 970, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 267, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200411/v2_16417a06088947debe0450950f8fc813_img_png", + "publish_date": "2020-04-11 16:59:15", + "publish_ip": "", + "last_modify_date": "2020-04-11 17:03:18", + "last_modify_ip": "", + "mode":2 + }, { + "user_id": 121373, + "user_name": "未来汽车日报", + "category_id": "223", + "title": "地方政府救市哪家强?广州补贴上万元,广深杭新增指标超5万", + "content": "", + "excerpt": "补贴很难落袋为安。", + "article_status": 1, + "view_count": 51662, + "like_count": 238, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 6217, + "last_comment_user_id": "", + "avatar": ["https://img.36krcdn.com/20200410/v2_6905947498bc4ec0af228afed409f771_img_png?x-oss-process=image/resize,m_mfit,w_520,h_300/crop,w_520,h_300,g_center","https://img.36krcdn.com/20200410/v2_6905947498bc4ec0af228afed409f771_img_png?x-oss-process=image/resize,m_mfit,w_520,h_300/crop,w_520,h_300,g_center","https://img.36krcdn.com/20200410/v2_6905947498bc4ec0af228afed409f771_img_png?x-oss-process=image/resize,m_mfit,w_520,h_300/crop,w_520,h_300,g_center"], + "publish_date": "2020-04-11 16:09:09", + "publish_ip": "", + "last_modify_date": "2020-04-11 16:11:11", + "last_modify_ip": "", + "mode":3 + }, { + "user_id": 121372, + "user_name": "智东西", + "category_id": "234", + "title": "救命呼吸机缺口难补!一文扒开供应链真相", + "content": "", + "excerpt": "全球疯抢国产呼吸机背后:技术有短板,产能被卡住。", + "article_status": 1, + "view_count": 77926, + "like_count": 2239, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 9154, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200410/v2_86bbf8245f754be79f3386a82b385093_img_000", + "publish_date": "2020-04-11 15:40:02", + "publish_ip": "", + "last_modify_date": "2020-04-11 15:53:10", + "last_modify_ip": "", + "mode":4 + }, { + "user_id": 121371, + "user_name": "神译局", + "category_id": "223", + "title": "每月节省32%的开支,我是怎么做到的?", + "content": "", + "excerpt": "开源节流", + "article_status": 1, + "view_count": 53577, + "like_count": 862, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 8073, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200408/v2_c67c3edfe4b5446992b32fad93a44a75_img_png", + "publish_date": "2020-04-11 14:48:02", + "publish_ip": "", + "last_modify_date": "2020-04-11 15:02:22", + "last_modify_ip": "", + "mode":5 + }, { + "user_id": 121369, + "user_name": "资本侦探", + "category_id": "221", + "title": "瓜子坚果双增长,但洽洽并不能高枕无忧", + "content": "", + "excerpt": "零食市场竞争日益激烈。", + "article_status": 1, + "view_count": 13740, + "like_count": 1354, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 7942, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200411/v2_2204c6132432403184e43df22485545e_img_000?x-oss-process=image/resize,m_mfit,w_432,h_288/crop,w_432,h_288,g_center", + "publish_date": "2020-04-11 14:23:00", + "publish_ip": "", + "last_modify_date": "2020-04-11 14:34:13", + "last_modify_ip": "", + "mode":6 + }, { + "user_id": 121367, + "user_name": "神译局", + "category_id": "103", + "title": "克服危机和压力,精神力量强大的人都有这5个习惯", + "content": "", + "excerpt": "学会利用好真正艰难的时刻,增强自己的精神力量", + "article_status": 1, + "view_count": 71706, + "like_count": 4978, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 5361, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200406/v2_d2c6a686b4074a1eb43603e67d6ba204_img_png", + "publish_date": "2020-04-11 13:47:01", + "publish_ip": "", + "last_modify_date": "2020-04-11 13:52:12", + "last_modify_ip": "", + "mode":1 + }, { + "user_id": 121365, + "user_name": "PingWest品玩", + "category_id": "221", + "title": "神州租车找爹记", + "content": "", + "excerpt": "一爹难求。", + "article_status": 1, + "view_count": 47794, + "like_count": 2397, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 9489, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200411/v2_f497b1c414d5489791569b3ea99df33d_img_000", + "publish_date": "2020-04-11 13:39:00", + "publish_ip": "", + "last_modify_date": "2020-04-11 13:44:11", + "last_modify_ip": "", + "mode":2 + }, { + "user_id": 121366, + "user_name": "明星八爪娱", + "category_id": "225", + "title": "抖音快手明星图鉴:哪个平台更适合明星“再就业”?", + "content": "", + "excerpt": "一个捧红了“十八线”明星,一个靠“偶像”获得新生", + "article_status": 1, + "view_count": 95348, + "like_count": 1356, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 356, + "last_comment_user_id": "", + "avatar": ["https://img.36krcdn.com/20200411/v2_da4c26244cbc494c8e0e5918518e866c_img_png","https://img.36krcdn.com/20200411/v2_da4c26244cbc494c8e0e5918518e866c_img_png","https://img.36krcdn.com/20200411/v2_da4c26244cbc494c8e0e5918518e866c_img_png"], + "publish_date": "2020-04-11 13:38:00", + "publish_ip": "", + "last_modify_date": "2020-04-11 13:44:11", + "last_modify_ip": "", + "mode":3 + }, { + "user_id": 121364, + "user_name": "神译局", + "category_id": "223", + "title": "动荡的市场中,你需要牢记巴菲特的这3个原则", + "content": "", + "excerpt": "本周股市下跌了不少——沃伦·巴菲特会作何反应?", + "article_status": 1, + "view_count": 86148, + "like_count": 4027, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 6620, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200406/v2_232e9248d5c74ff989db57a0b6713abe_img_png", + "publish_date": "2020-04-11 12:45:02", + "publish_ip": "", + "last_modify_date": "2020-04-11 12:51:10", + "last_modify_ip": "", + "mode":4 + }, { + "user_id": 121362, + "user_name": "资本侦探", + "category_id": "0", + "title": "连亏六年、股价跌破1美元,曾经的明星公司途牛怎么了?", + "content": "", + "excerpt": "携程、京东、红杉共同加持也无济于事。", + "article_status": 1, + "view_count": 83493, + "like_count": 1771, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 2211, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200411/v2_61c1766736df49a0b2d0213624c0ebd2_img_000?x-oss-process=image/resize,m_mfit,w_432,h_288/crop,w_432,h_288,g_center", + "publish_date": "2020-04-11 12:37:11", + "publish_ip": "", + "last_modify_date": "2020-04-11 12:41:10", + "last_modify_ip": "", + "mode":5 + }, { + "user_id": 121363, + "user_name": "Tech星球", + "category_id": "0", + "title": "独家 | 快手版「多闪」上线:「一甜面聊」布局视频社交", + "content": "", + "excerpt": "视频社交的时代来了。", + "article_status": 1, + "view_count": 97790, + "like_count": 636, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 4027, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200411/v2_b92317dfc59948cea0f3c69a0357e519_img_000?x-oss-process=image/resize,m_mfit,w_432,h_288/crop,w_432,h_288,g_center", + "publish_date": "2020-04-11 12:36:58", + "publish_ip": "", + "last_modify_date": "2020-04-11 12:41:11", + "last_modify_ip": "", + "mode":6 + }, { + "user_id": 121361, + "user_name": "神译局", + "category_id": "103", + "title": "2020年已经过去了四分之一,但改变自己为时不晚", + "content": "", + "excerpt": "种一棵树最好的时间是十年前,其次是现在", + "article_status": 1, + "view_count": 67302, + "like_count": 4148, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 286, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200404/v2_d6613223fb15414897a0ba3449d00afd_img_png", + "publish_date": "2020-04-11 11:44:00", + "publish_ip": "", + "last_modify_date": "2020-04-11 11:52:11", + "last_modify_ip": "", + "mode":1 + }, { + "user_id": 121360, + "user_name": "沈帅波", + "category_id": "221", + "title": "2020,市场部求生指南", + "content": "", + "excerpt": "短期思维的套利空间正在逐渐消失。", + "article_status": 1, + "view_count": 91108, + "like_count": 4029, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 7126, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200410/v2_c5997a3640f54c2c880cff0906f6896c_img_000", + "publish_date": "2020-04-11 11:31:00", + "publish_ip": "", + "last_modify_date": "2020-04-11 11:33:15", + "last_modify_ip": "", + "mode":2 + }, { + "user_id": 121359, + "user_name": "陈淑雅", + "category_id": "223", + "title": "定位新媒体整合营销服务商,「通明传媒」用“小V矩阵”打出差异化", + "content": "", + "excerpt": "近期通明传媒还成为了罗永浩抖音直播的官方授权招商服务合作伙伴。", + "article_status": 1, + "view_count": 38875, + "like_count": 4717, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 9477, + "last_comment_user_id": "", + "avatar": ["https://img.36krcdn.com/20200410/v2_224a699a06504292804e4bdf70ca87bb_img_png","https://img.36krcdn.com/20200410/v2_224a699a06504292804e4bdf70ca87bb_img_png","https://img.36krcdn.com/20200410/v2_224a699a06504292804e4bdf70ca87bb_img_png"], + "publish_date": "2020-04-11 11:09:58", + "publish_ip": "", + "last_modify_date": "2020-04-11 11:21:10", + "last_modify_ip": "", + "mode":3 + }, { + "user_id": 121358, + "user_name": "来咖智库", + "category_id": "0", + "title": "BAT的直播电商新战事", + "content": "", + "excerpt": "阿里做大、腾讯做深、百度做新。", + "article_status": 1, + "view_count": 41013, + "like_count": 3650, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 682, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200410/v2_747fc8a18fde4da4b1ba1080d8e6aa04_img_000", + "publish_date": "2020-04-11 11:06:00", + "publish_ip": "", + "last_modify_date": "2020-04-11 11:12:11", + "last_modify_ip": "", + "mode":4 + }, { + "user_id": 121357, + "user_name": "创业最前线", + "category_id": "0", + "title": "估值50亿美元,“种草”社区头牌,小红书如何走出商业化迷途?", + "content": "", + "excerpt": "小红书求变。", + "article_status": 1, + "view_count": 36498, + "like_count": 1523, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 8731, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200410/v2_18c3a78cf8be42ccb45e4daba0c87c13_img_png", + "publish_date": "2020-04-11 10:41:00", + "publish_ip": "", + "last_modify_date": "2020-04-11 10:53:11", + "last_modify_ip": "", + "mode":5 + }, { + "user_id": 121356, + "user_name": "神译局", + "category_id": "223", + "title": "在混乱和不确定的时期,你最需要的是这5个技能", + "content": "", + "excerpt": "自律就是即使你不想做某件事,但也能强迫自己去做的能力。", + "article_status": 1, + "view_count": 13776, + "like_count": 2214, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 9514, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200401/v2_4afb7581cb5a4c36aac96a51829c13e0_img_png", + "publish_date": "2020-04-11 10:40:01", + "publish_ip": "", + "last_modify_date": "2020-04-11 10:41:11", + "last_modify_ip": "", + "mode":6 + }, { + "user_id": 121355, + "user_name": "音乐先声", + "category_id": "0", + "title": "复工按下暂停键,演出报批遥遥无期,线下音乐路在何方?", + "content": "", + "excerpt": "阴霾终究会散去。", + "article_status": 1, + "view_count": 96989, + "like_count": 3607, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 3580, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200410/v2_41365a0f26a244fdab8e3f5be081ed2b_img_000", + "publish_date": "2020-04-11 10:06:00", + "publish_ip": "", + "last_modify_date": "2020-04-11 10:11:12", + "last_modify_ip": "", + "mode":1 + }, { + "user_id": 121354, + "user_name": "36氪出海", + "category_id": "0", + "title": "出海创投周报|阿里领投印度BigBasket6000万美元融资;Reliance向AI教育平台Embibe追加6600万美元投资", + "content": "", + "excerpt": "出海人的周末精选读物。", + "article_status": 1, + "view_count": 63561, + "like_count": 3817, + "is_sticky": false, + "is_essence": false, + "comment_status": 0, + "comment_count": 1433, + "last_comment_user_id": "", + "avatar": "https://img.36krcdn.com/20200410/v2_fb948f4c18de4b22927f0361d53f6caf_img_png", + "publish_date": "2020-04-11 10:00:01", + "publish_ip": "", + "last_modify_date": "2020-04-11 10:03:18", + "last_modify_ip": "", + "mode":2 + }] + } +} diff --git a/uniCloud-alipay/database/opendb-news-articles.schema.json b/uniCloud-alipay/database/opendb-news-articles.schema.json new file mode 100644 index 0000000..18c4f0d --- /dev/null +++ b/uniCloud-alipay/database/opendb-news-articles.schema.json @@ -0,0 +1,122 @@ +{ + "bsonType": "object", + "permission": { + "create": "auth.uid != null", + "delete": "doc.uid == auth.uid", + "read": true, + "update": "doc.uid == auth.uid" + }, + "properties": { + "_id": { + "description": "存储文档 ID(用户 ID),系统自动生成" + }, + "article_status": { + "bsonType": "int", + "description": "文章状态:0 草稿箱 1 已发布", + "maximum": 1, + "minimum": 0 + }, + "avatar": { + "bsonType": "string", + "description": "缩略图地址", + "label": "封面大图" + }, + "category_id": { + "bsonType": "string", + "description": "分类 id,参考`uni-news-categories`表" + }, + "comment_count": { + "bsonType": "int", + "description": "评论数量", + "permission": { + "write": false + } + }, + "comment_status": { + "bsonType": "int", + "description": "评论状态:0 关闭 1 开放", + "maximum": 1, + "minimum": 0 + }, + "content": { + "bsonType": "string", + "description": "文章内容", + "label": "文章内容" + }, + "excerpt": { + "bsonType": "string", + "description": "文章摘录", + "label": "摘要" + }, + "is_essence": { + "bsonType": "bool", + "description": "阅读加精", + "permission": { + "write": false + } + }, + "is_sticky": { + "bsonType": "bool", + "description": "是否置顶", + "permission": { + "write": false + } + }, + "last_comment_user_id": { + "bsonType": "string", + "description": "最后回复用户 id,参考`uni-id-users` 表" + }, + "last_modify_date": { + "bsonType": "timestamp", + "description": "最后修改时间" + }, + "last_modify_ip": { + "bsonType": "string", + "description": "最后修改时 IP 地址" + }, + "like_count": { + "bsonType": "int", + "description": "喜欢数、点赞数", + "permission": { + "write": false + } + }, + "mode": { + "bsonType": "number", + "description": "排版显示模式" + }, + "publish_date": { + "bsonType": "timestamp", + "defaultValue": { + "$env": "now" + }, + "description": "发表时间" + }, + "publish_ip": { + "bsonType": "string", + "description": "发表时 IP 地址", + "forceDefaultValue": { + "$env": "clientIP" + } + }, + "title": { + "bsonType": "string", + "description": "标题", + "label": "标题" + }, + "user_id": { + "bsonType": "string", + "description": "文章作者ID, 参考`uni-id-users` 表" + }, + "view_count": { + "bsonType": "int", + "description": "阅读数量", + "permission": { + "write": false + } + } + }, + "required": ["user_id", "title", "content", "article_status", "view_count", "like_count", "is_sticky", "is_essence", + "comment_status", "comment_count", "mode" + ] +} diff --git a/uni_modules/uni-badge/changelog.md b/uni_modules/uni-badge/changelog.md new file mode 100644 index 0000000..550eb41 --- /dev/null +++ b/uni_modules/uni-badge/changelog.md @@ -0,0 +1,14 @@ +## 1.1.1(2021-05-12) +- 新增 组件示例地址 +## 1.1.0(2021-05-12) +- 新增 uni-badge 的 absolute 属性,支持定位 +- 新增 uni-badge 的 offset 属性,支持定位偏移 +- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点 +- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+ +- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式 +## 1.0.7(2021-05-07) +- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug +- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug +- 新增 uni-badge 属性 custom-style, 支持自定义样式 +## 1.0.6(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-badge/components/uni-badge/uni-badge.vue b/uni_modules/uni-badge/components/uni-badge/uni-badge.vue new file mode 100644 index 0000000..efe2812 --- /dev/null +++ b/uni_modules/uni-badge/components/uni-badge/uni-badge.vue @@ -0,0 +1,252 @@ + + + + + + + + diff --git a/uni_modules/uni-badge/package.json b/uni_modules/uni-badge/package.json new file mode 100644 index 0000000..4b0c851 --- /dev/null +++ b/uni_modules/uni-badge/package.json @@ -0,0 +1,84 @@ +{ + "id": "uni-badge", + "displayName": "uni-badge 数字角标", + "version": "1.1.1", + "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。", + "keywords": [ + "", + "badge", + "uni-ui", + "uniui", + "数字角标", + "徽章" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "y", + "联盟": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-badge/readme.md b/uni_modules/uni-badge/readme.md new file mode 100644 index 0000000..e035449 --- /dev/null +++ b/uni_modules/uni-badge/readme.md @@ -0,0 +1,58 @@ + + +## Badge 数字角标 +> **组件名:uni-badge** +> 代码块: `uBadge` + + +数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景, + +### 安装方式 + +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 + +如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) + +### 基本用法 + +在 ``template`` 中使用组件 + +```html ++ {{displayValue}} ++ + ++ + + +``` + + +## API + +### Badge Props + +|属性名 |类型 |默认值 |说明 | +|:-: |:-: |:-: |:-: | +|text |String |- |角标内容 | +|type |String |default|颜色类型,可选值:default(灰色)、primary(蓝色)、success(绿色)、warning(黄色)、error(红色)| +|size |String |normal |Badge 大小,可取值:normal、small | +|is-dot |Boolean|false |不展示数字,只有一个小点 | +|max-num |String/Numbuer|99 |展示封顶的数字值,超过 99 显示99+ | +|custom-style |Object | {} |自定义 Badge 样式, 样式对象语法 | +|inverted |Boolean|false |是否无需背景颜色,为 true 时,背景颜色将变为文字的字体颜色 | +|absolute |String| rightTop|开启绝对定位, 角标将定位到其包裹的标签的四个角上,可选值: rightTop(右上角)、rightBottom(右下角)、leftBottom(左下角) 、leftTop(左上角) | +|offset |Array[number]| [0, 0]|距定位角中心点的偏移量,[-10, -10] 表示向 absolute 指定的方向偏移 10px,[10, 10] 表示向 absolute 指定的反方向偏移 10px,只有存在 absolute 属性时有效,与absolute 的值一一对应(例如:值为rightTop, 对应 offset 为 [right, Top])| + +### Badge Events + +|事件名 |事件说明 |返回参数 | +|:-: |:-: |:-: | +|@click |点击 Badge 触发事件| - | + + + + +## 组件示例 + +点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/badge/badge](https://hellouniapp.dcloud.net.cn/pages/extUI/badge/badge) \ No newline at end of file diff --git a/uni_modules/uni-config-center/changelog.md b/uni_modules/uni-config-center/changelog.md new file mode 100644 index 0000000..4d2eb92 --- /dev/null +++ b/uni_modules/uni-config-center/changelog.md @@ -0,0 +1,4 @@ +## 0.0.2(2021-04-16) +- 修改插件package信息 +## 0.0.1(2021-03-15) +- 初始化项目 diff --git a/uni_modules/uni-config-center/package.json b/uni_modules/uni-config-center/package.json new file mode 100644 index 0000000..c5dec93 --- /dev/null +++ b/uni_modules/uni-config-center/package.json @@ -0,0 +1,80 @@ +{ + "id": "uni-config-center", + "displayName": "uni-config-center", + "version": "0.0.2", + "description": "uniCloud 配置中心", + "keywords": [ + "配置", + "配置中心" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "category": [ + "uniCloud", + "云函数模板" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "directories": { + "example": "../../../scripts/dist" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "u", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} diff --git a/uni_modules/uni-config-center/readme.md b/uni_modules/uni-config-center/readme.md new file mode 100644 index 0000000..03f7fc2 --- /dev/null +++ b/uni_modules/uni-config-center/readme.md @@ -0,0 +1,93 @@ +# 为什么使用uni-config-center + +实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构 + +```bash +cloudfunctions +└─────common 公共模块 + ├─plugin-a // 插件A对应的目录 + │ ├─index.js + │ ├─config.json // plugin-a对应的配置文件 + │ └─other-file.cert // plugin-a依赖的其他文件 + └─plugin-b // plugin-b对应的目录 + ├─index.js + └─config.json // plugin-b对应的配置文件 +``` + +假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。 + +uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下 + +```bash +cloudfunctions +└─────common 公共模块 + ├─plugin-a // 插件A对应的目录 + │ └─index.js + ├─plugin-b // plugin-b对应的目录 + │ └─index.js + └─uni-config-center + ├─index.js // config-center入口文件 + ├─plugin-a + │ ├─config.json // plugin-a对应的配置文件 + │ └─other-file.cert // plugin-a依赖的其他文件 + └─plugin-b + └─config.json // plugin-b对应的配置文件 +``` + +使用uni-config-center后的优势 + +- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便 +- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持) + +# 用法 + +在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common) + +```js +const createConfig = require('uni-config-center') + +const uniIdConfig = createConfig({ + pluginId: 'uni-id', // 插件id + defaultConfig: { // 默认配置 + tokenExpiresIn: 7200, + tokenExpiresThreshold: 600, + }, + customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并 + // defaudltConfig 默认配置 + // userConfig 用户配置 + return Object.assign(defaultConfig, userConfig) + } +}) + + +// 以如下配置为例 +// { +// "tokenExpiresIn": 7200, +// "passwordErrorLimit": 6, +// "bindTokenToDevice": false, +// "passwordErrorRetryTime": 3600, +// "app-plus": { +// "tokenExpiresIn": 2592000 +// }, +// "service": { +// "sms": { +// "codeExpiresIn": 300 +// } +// } +// } + +// 获取配置 +uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象 +uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200 +uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300 +uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600 + +// 获取文件绝对路径 +uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径 + +// 引用文件(require) +uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。 + +// 判断是否包含某文件 +uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在 +``` \ No newline at end of file diff --git a/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js new file mode 100644 index 0000000..e14fb3b --- /dev/null +++ b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js @@ -0,0 +1 @@ +"use strict";var t=require("fs"),r=require("path");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t),o=e(r),i="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var u=function(t){var r={exports:{}};return t(r,r.exports),r.exports}((function(t,r){var e="__lodash_hash_undefined__",n=9007199254740991,o="[object Arguments]",u="[object Function]",c="[object Object]",a=/^\[object .+?Constructor\]$/,f=/^(?:0|[1-9]\d*)$/,s={};s["[object Float32Array]"]=s["[object Float64Array]"]=s["[object Int8Array]"]=s["[object Int16Array]"]=s["[object Int32Array]"]=s["[object Uint8Array]"]=s["[object Uint8ClampedArray]"]=s["[object Uint16Array]"]=s["[object Uint32Array]"]=!0,s[o]=s["[object Array]"]=s["[object ArrayBuffer]"]=s["[object Boolean]"]=s["[object DataView]"]=s["[object Date]"]=s["[object Error]"]=s[u]=s["[object Map]"]=s["[object Number]"]=s[c]=s["[object RegExp]"]=s["[object Set]"]=s["[object String]"]=s["[object WeakMap]"]=!1;var l="object"==typeof i&&i&&i.Object===Object&&i,h="object"==typeof self&&self&&self.Object===Object&&self,p=l||h||Function("return this")(),_=r&&!r.nodeType&&r,v=_&&t&&!t.nodeType&&t,d=v&&v.exports===_,y=d&&l.process,g=function(){try{var t=v&&v.require&&v.require("util").types;return t||y&&y.binding&&y.binding("util")}catch(t){}}(),b=g&&g.isTypedArray;function j(t,r,e){switch(e.length){case 0:return t.call(r);case 1:return t.call(r,e[0]);case 2:return t.call(r,e[0],e[1]);case 3:return t.call(r,e[0],e[1],e[2])}return t.apply(r,e)}var w,O,m,A=Array.prototype,z=Function.prototype,M=Object.prototype,x=p["__core-js_shared__"],C=z.toString,F=M.hasOwnProperty,U=(w=/[^.]+$/.exec(x&&x.keys&&x.keys.IE_PROTO||""))?"Symbol(src)_1."+w:"",S=M.toString,I=C.call(Object),P=RegExp("^"+C.call(F).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),T=d?p.Buffer:void 0,q=p.Symbol,E=p.Uint8Array,$=T?T.allocUnsafe:void 0,D=(O=Object.getPrototypeOf,m=Object,function(t){return O(m(t))}),k=Object.create,B=M.propertyIsEnumerable,N=A.splice,L=q?q.toStringTag:void 0,R=function(){try{var t=_t(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),G=T?T.isBuffer:void 0,V=Math.max,W=Date.now,H=_t(p,"Map"),J=_t(Object,"create"),K=function(){function t(){}return function(r){if(!Mt(r))return{};if(k)return k(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Q(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r -1},X.prototype.set=function(t,r){var e=this.__data__,n=nt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this},Y.prototype.clear=function(){this.size=0,this.__data__={hash:new Q,map:new(H||X),string:new Q}},Y.prototype.delete=function(t){var r=pt(this,t).delete(t);return this.size-=r?1:0,r},Y.prototype.get=function(t){return pt(this,t).get(t)},Y.prototype.has=function(t){return pt(this,t).has(t)},Y.prototype.set=function(t,r){var e=pt(this,t),n=e.size;return e.set(t,r),this.size+=e.size==n?0:1,this},Z.prototype.clear=function(){this.__data__=new X,this.size=0},Z.prototype.delete=function(t){var r=this.__data__,e=r.delete(t);return this.size=r.size,e},Z.prototype.get=function(t){return this.__data__.get(t)},Z.prototype.has=function(t){return this.__data__.has(t)},Z.prototype.set=function(t,r){var e=this.__data__;if(e instanceof X){var n=e.__data__;if(!H||n.length<199)return n.push([t,r]),this.size=++e.size,this;e=this.__data__=new Y(n)}return e.set(t,r),this.size=e.size,this};var it,ut=function(t,r,e){for(var n=-1,o=Object(t),i=e(t),u=i.length;u--;){var c=i[it?u:++n];if(!1===r(o[c],c,o))break}return t};function ct(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":L&&L in Object(t)?function(t){var r=F.call(t,L),e=t[L];try{t[L]=void 0;var n=!0}catch(t){}var o=S.call(t);n&&(r?t[L]=e:delete t[L]);return o}(t):function(t){return S.call(t)}(t)}function at(t){return xt(t)&&ct(t)==o}function ft(t){return!(!Mt(t)||function(t){return!!U&&U in t}(t))&&(At(t)?P:a).test(function(t){if(null!=t){try{return C.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function st(t){if(!Mt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=dt(t),e=[];for(var n in t)("constructor"!=n||!r&&F.call(t,n))&&e.push(n);return e}function lt(t,r,e,n,o){t!==r&&ut(r,(function(i,u){if(o||(o=new Z),Mt(i))!function(t,r,e,n,o,i,u){var a=yt(t,e),f=yt(r,e),s=u.get(f);if(s)return void rt(t,e,s);var l=i?i(a,f,e+"",t,r,u):void 0,h=void 0===l;if(h){var p=wt(f),_=!p&&mt(f),v=!p&&!_&&Ct(f);l=f,p||_||v?wt(a)?l=a:xt(j=a)&&Ot(j)?l=function(t,r){var e=-1,n=t.length;r||(r=Array(n));for(;++e -1&&t%1==0&&t 0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(R?function(t,r){return R(t,"toString",{configurable:!0,enumerable:!1,value:(e=r,function(){return e}),writable:!0});var e}:It);function bt(t,r){return t===r||t!=t&&r!=r}var jt=at(function(){return arguments}())?at:function(t){return xt(t)&&F.call(t,"callee")&&!B.call(t,"callee")},wt=Array.isArray;function Ot(t){return null!=t&&zt(t.length)&&!At(t)}var mt=G||function(){return!1};function At(t){if(!Mt(t))return!1;var r=ct(t);return r==u||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}function zt(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=n}function Mt(t){var r=typeof t;return null!=t&&("object"==r||"function"==r)}function xt(t){return null!=t&&"object"==typeof t}var Ct=b?function(t){return function(r){return t(r)}}(b):function(t){return xt(t)&&zt(t.length)&&!!s[ct(t)]};function Ft(t){return Ot(t)?tt(t,!0):st(t)}var Ut,St=(Ut=function(t,r,e){lt(t,r,e)},ht((function(t,r){var e=-1,n=r.length,o=n>1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=Ut.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!Mt(e))return!1;var n=typeof r;return!!("number"==n?Ot(e)&&vt(r,e.length):"string"==n&&r in e)&&bt(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e c.call(t,r);class f{constructor({pluginId:t,defaultConfig:r={},customMerge:e,root:n}){this.pluginId=t,this.defaultConfig=r,this.pluginConfigPath=o.default.resolve(n||__dirname,t),this.customMerge=e,this._config=void 0}resolve(t){return o.default.resolve(this.pluginConfigPath,t)}hasFile(t){return n.default.existsSync(this.resolve(t))}requireFile(t){try{return require(this.resolve(t))}catch(t){if("MODULE_NOT_FOUND"===t.code)return;throw t}}_getUserConfig(){return this.requireFile("config.json")}config(t,r){this._config||(this._config=(this.customMerge||u)(this.defaultConfig,this._getUserConfig()));let e=this._config;return t?function(t,r,e){if("number"==typeof r)return t[r];if("symbol"==typeof r)return a(t,r)?t[r]:e;const n="string"!=typeof(o=r)?o:o.split(".").reduce(((t,r)=>(r.split(/\[([^}]+)\]/g).forEach((r=>r&&t.push(r))),t)),[]);var o;let i=t;for(let t=0;t + + + + + + + diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue new file mode 100644 index 0000000..6319565 --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue @@ -0,0 +1,71 @@ + +{{unicode}} +{{icons[type]}} + + + + + diff --git a/uni_modules/uni-icons/components/uni-icons/uni.ttf b/uni_modules/uni-icons/components/uni-icons/uni.ttf new file mode 100644 index 0000000000000000000000000000000000000000..60a1968d08cc6056c70b5402b2effac43c6f96a3 GIT binary patch literal 26164 zcmd_TX?z^TwKv?SdZuUZ*{5e;H8a|*T^d=EEqULKckpgml5KgDk!);i2nH_%0>luO zfPriTxR4OC00t6b2;2t}2qA%7wj=~>Fd>kT3xQvPTF<|_N4Df(=f3y-@P2qDb$4}D zb=Rq?Q>V__5=amPo3K|9g_?5~R@W^Zx8lD9ftr!KrfW;*w!{L<_XI(_8%KJ5=fJk1 zA=DJsRifOye)EOvZhZIVd4gbiSrC>)H}rINE8h@~qU^^wnl>QA^bf;6q(8z@vSG{i zT`W{~i_ZKJ~i+M*!pC%1NP=}G-?!i$2i63^2U z+xiB!_dU4dZ-TJ;2%b4#;IQNP?t51qT E>Nw44LNt%6<4;!j%fi`Nyah~j5-NHC%wS1>>? zd|AKJdqN$Vkt-N6PQyR0;RLSp)=lXaIt1awyE+WwUW~p56Mu?5hctflo*;X%mY#+C zD{!Q6@bpbM%5bd2k;hSrgFiEH+I`ZnS6Ga^-8guiTX9^6!;IrO9M9nRUGcgLR|&^N z97}L)#Ie74@HT6U2Tw G?BI=Pd&Uvsjmx$8c=H@ipXk=!b9w_ck2-eZ1}V zVw&H-fTJ77J{-IbFX#FE;Q8}#%*Vm|Wx&DV=IvdjA5@Jts*rxPc=Y3ngW|Y4aE!$P zI8OGDkBu9L2M33rx5M8zd~i7Un6?$K93GzLS3btM;_+KtC!n3xxUR>+-^2UG$9VW% zJdck%zvpAk`@pYLw5vym7JpHLuRHB1Vk?W{j<0~IV9*fzB4CwKXhTlykL-_iZ;Ef$ zzuEnk_*VT}Yu@TUW;y0Q)^Kd>v5CjJj;%Yk;aLB1^YNPFb;lcz7mlwv-gUg^_=e+O zJbvhH%iErJe*4ZV@BHPRkKg&n2|AHI(Q#thiMc11oLF&U)rsyC8%}IJvGc^96Z=nG zcj6l-?l|$i6W>4a(-W_sc>Bb=pbh*d_DA85HE#-U*1WmqE#a*?wBB`0IOam@g<~DZ z)*S0W>)VbCTI&s3>ub^a`r~^?wf>RTdiq2wTAy=T>%0G@^#(x{P#C{k1 zek>3@5&d!Wk!T_sihL6JIP#asuOlx+eieBp(iZVYd=YQN6aG{9-SCO &Px{ET#PnzLJoA<2H!L2@EtX@}4(pXRpKYV c8QJ$fY865AHLGwzCS zh(De1C8`qFCs}eq^2+1~sjsIE>6-MLnTE{%%!?&$C7Vm`EO|BCkX@U-HT!mMeD15c zU*#v}@5_H$T3*^;`b1ev*^}iZ<@Z&{pbfKzejz>}Hez>=31xy{98ZNR%FASmlNV>C zkrOAyCl%AfrA#>TsnPi9k%vFw=e1X*D{9E_?5&5NGt^e3uUgx_kl2ED?c9iRz3!1u zDNbYaH5W}oHN$g uM3W6LH@UCOb~AY3u@H*u%v08EOI7RCTuM?l5F z(?ODnQh~e |Jr0*GkF*p@kJElpkieM$QM@~IQa(Rzg>UD4_w zP|wuRcf>cuMH+mSLbHI~_e>C)(vm5laKMy6J|&qnfJaqM=f+W{iW-_)sj;D{E)b*o zx&THy gtkl1e*pq{AF29JeJu6o15yd?# zZ0-d%r_;8;t+@1ri~bL~x_Aq^x^QuSJI!t#J45g4&QKr_O_0{XRFZdFO|gsc9{#qK zduGax^T-)+F15?DeJK)jo SJB1=^VborpFe-2+8>QAy<3v* zUK)#XTr3; #o7eGF7f}4#yjGB3 zCf26`p@TB5usUDeWTq{3 kxrSK$%A4z(J^$r8vdrr`o z+d3hch((v)tyZ#&mahN`@Tr^0r%D-~GcAF!S~>K(c!yXb8ke z4KC)r7|-UE+CX@GLyOOaS4oTPd7rr!9YjB!;w$V!!2wzl6H-EzAQU)OxEnI5wB&dD zEYwt=s#8cx8{LhHDM#*nfztV`5-0@P$tY#M%YM+>esFMZO9$Pl{#f?0dwfpyCy_dJ z? esiY7vD3ZaH z&e!H7lf)+qSl3flktzA!F@xdQ_i&!v?jdFhg(z%Se_ ^R1=Ljajp>VP=`r5=z0*m3++;43Y|PbsW=H$blU`#`NL_`-LOCyX){K?Y@h zpJFm%y=Wzk!zD7mmrNfzLatr;S$lT60uGPQIe8w@yvfZpZ-&aIaT+nLx`~|jsWlBm z4K?%$uJ2BpL#BN!*KhU67mTSTsvSd%^lQ%Uq>SCUse;xyoTT^{)9h)#o;I5zGtMD8 zXNLL^uASxIa>?~|G^MV-zAnTo#DW***IP_A)xWB)(N3}xV?e^d(1+sHqEo2EEOCO4 z717v` G<)?6s}{C;ybkC7m=cX9Og@uu+=P0YQHq0j ztO%C)%e{#h+x6V4J&fAD6#-Y=w$e}WxMZ-`PZ;MjdrZk_REb}jAg?Drqioglpi9Ge zZ57<0dZ4@%C;*UD+C%}Pg*av#IhN-wl&UL`NlI4}1sH`Rv_059IJe-Zoe^~wRja?U zig#Nr>I ~->LDN1 zMa#>h>hpd+Hp4g^5Cre%<7w%ckdeOoxmXA8bm#}bx%VNvG!`)q$OU|9CBEyAz_I|? zmQy&0f*AR9 IA$uMoa>TJjEKC`{e&6YadIsHbxW#aVd69@J=JQ16H zt*xr^uZvd7&Dd?HPEc>1IE#ASzIyVxHqxvKznd_XXa8=(EZS+e3nn2cgvEb|P1qlj zz>8*KvM@(jf&ppDnWS8yDS$K9Xdb-DcuWGwC~^WyfQeNE^uY2#z9 L>HYy zCW g~6FD9xID{clo+pg6EUZLruL`eoSm-QByt zYShl5jGW!LFDi|5=8vfV72Ywfr92qf+}c+Au(wpPWXprLa+A|6I$dT1^JZ!#vB_rd znHqDeIl6pT`<0WgHXL*tsk&yh!y?X6e}RR#%qs7mKX19!xtmS2w~OvWy(PZXSDqdG zMsuylzq+BmMs}|>%h?jQoGVF*lI$=^P6yVGBrG2KJ2Wg-As{4#QeiB1(m5EVIt60` zih$WN6+lYr3OUSgo-;sv>ooBbzu`lOYFKo2O$7z~UzV5P37=GdGR59 5UPbv2 z+2?oQ$|7vz0fq`ww~txhX0n2O4SaQtf`{|UV*R3i(0i3AUe&wtD$! B2nWJkSprn<;2!)*n#n3i+JmO`AYa8goX; z F17&C+*`>`-9N;C}zy zMl!IwaUAl`X`J#L-ta!2R7@X;#^ Tck~jFT}eWWNtX)4+S4 zLjm8f11OMq1rruhTJi;e7bg=9IX#D}T@ml~ t zln?USso #@2*^ SFekMi7jWfrV XS4ZymMt=U@H&5hpH`vr>--TaiB~)@+hUAMR@*_FRf-$4=SiZ)V^iO> zc`VFyp3S|@t>cS%=pFG>F(gEUR$&^Xu5RoKsiuNkLk!LeaR!33t+<-p0kGg4Td;O8 z!hF}L12YxZt{V1aPjXq <)$<8D~CqZ?e>x zafE}N$hGAyzSI*=0dU7tuezkr7 ^HzuHp;%B$g;;B;?lXmW?U07GQu$I*0 zvd1ISB@VCG@%4+ZXWodHF5T958F|BAV%J|xH;_DQIb+LbsehZbf@sC8n#jl4}Zu zn!$yrjlXXD*Y}>wU$D6EGR7|JTg=nv?)|#G8@%x|Lr;nYu>cC1Kri%8#JL~>f{1MZ z@B%i8fxpS;82f--ws9j~vU#c1R${X*-8}d^@&5h$?-wmcX87v8Gmg+}mtISB?WMDR zy+d|5 16dFKN}58Sy=eR)YBu$Zt^neaQbnGxGCc1@>`9EQag&_@fr?(k@tAk%51 z#Ys?%lVU%+jHb1;Oe5{AKE%63hxqyKonInP*h6&jx^)+mmi*EMw3q6}%?7JDPW@%u z90Ij|oR1(M#8viNcJ??t9!F0%7wo$A^v+xCt1!=}#z%&HDtJc^$4CT!=CpCBsvZw{ zwOTvVYo`rD%Ww(GL8o^O9ThJZJHTnigz>^m&i|v2F>S*EQh~9?NMJ^q8uAb%As%`; z{XL0OO@+LsJSrjd|9J}N*|&Nt>cyL=*BIgy<+v1PV}+NqMhWQ};O zgALY*&wBf*QM_wGYgOZ{br&&D#KW%KNt5`H8XKMJOQ90EQF5kpG?C_rjOz2hoJjKI zB}9{&9OEnV^@B01H)3VaS$z@fU_c+_Rp#=l5@Ht*5AI?6D*B@~=Alr1RpBcZOM|H_ z9iFsk<_x~Jq@j<&^VwkaNeC632GxNE<-vNp1NA^rC&+sqd$hZ_QH`92tJ&L}m<)#b znN5gIi# bYSqK19VlGBHx`Jq~HL(JPG6= z{~KySCC0{9l#c}-7=(#KFNlwc)u4@8jSt063XY)>Z~>CMCf@VCv>v%iAe+YGZzs1& zGJ=}BAy>E|-v<;om+slsLGK^4RO9p=d)Hgz`+Y8~IQ_4@A5?>qeDn#CervHj;`r&5 zCk)I;@^`G&woCjKY(Wj#zHp7*eu=+)@V;Q!zT<$s*TlR|OW)wLn@Bbqds&@%`{47e zv6m4^gYUb{-H?4nVad>Q;+ dcx@O(nFu zMLjrAvZ_CuG?9KcMctH2Poj4wP1&z{4sc#| ${dW2(nMNDk2rYowN)m1^?jlSRq)4V~7GiQ{7zIK~Tb{QncA^*2c zb~ydAgB*7_{TMTxBsSmy5$>pJB5JDYAWzgYcy)CnQKOjfD2k_TFi$}*+dOzZ-Z t$RlHd229;^XSa1bO9x5PhvVdT+MvqNE zFfrAHNy=xqwoB*Hz)dt2>Y)q6Efb(WS!s=Utk>GZ_G>NVj#^iVz7zE4%dwm8ydarQ zCsl>(IWO3C@Xt^{AL;0_x+0dV?DnfHVYjt=f;wIHs`q2pylX#ANvG9LY?hPgYm;co z0d*;6kJH5cL*ECibBAHYI>2B%i(~G0D_9N^SOJb&r@_h*jKj+LP9`|)*IGRh>q_Q} z`ovY%sGF>Z?C Fth+Bd_zOGel*`)PK~KtFudKFpbOUbdmmKPe{q!h6&7{;h z>C`0pAt0sw>XZYg=}sHK`+|B8Z*V-J6LXoe+M3nI8moi%gm(a9feBQ0v@Vsa)ioWw z_)GQIPV4Rqt#Pk)_a3V+YTdKP8ueLs@3#6z>QyJ})uD^O_1PcTQ0k3aP#-n-ARR+} zOWe!Hw07w4;`5>fQp|XbOD|wh^B{H^zTssgrhuCaa3NRc*3;k+O?;I|X}(L=2XNm6 zEnC260)?q?MqRW(QPlf9A*T{`y!{eU$RkH=&3El_M5`sa<>n`{%*ej;N{cL-M5=`X z>v@AkmZ=@)HfnP@ e*tFc@$D&_vFAL{U^ JBVVW1Sir7Qry$4RCSzh*EjSdArpr$#4F*=ZE6g+3FmaNYys zt&tg>C&68vVv;~;_&NY>)lesgxj8fHe4A}vFn<$s2i >YTfF8g%)f-Vq(>oWkbudJrG$5e>sn^1#Z@pF8 z=vsQb)K{mzv)DPowOD =8<=>T z%XK@HRikYoXIamDVK)wMCOXGh+)5yOoN-cab$jWcC*b!UByZYt&>K)Z2R&z+fLqD$ zy~LC85b6c+1d^9{pqd*EW9BS)qzMFEz&;B|>JeJXAyV%GG-m>ZCVSFeK#aK_iNj~a z;4==unHtb({;7ADp4KbqhuT3gL4Fe8F0h9J#UTGwgEoz7EAI5$_U^U$
GlPi7$wX>mwAa9 z&zbQs1aq1-wq+J$vs&zKw|yZuc>-pbE>5n&v#h|gt**1Io6%$PuX6+ACs*K&G=6gV zof|(#8kisQc(3+i-mdnR_^t+tMrzbP_L|~7;LUok;dQP-;(!m>KDupX^n7@Evyf4M z3z<<(iBK5&Xd~1B-cdt(C0>ia|M?o?>wI`WAJxK<5!>|P?YE2K?b|Q74d;=~jog?Q zh_~<9!K>lS`!r+d8Sx>=#9Zer7)NjlUX9NOYU@N^Gto6L;Sp}Ae?&XmEMd#j){v#u z8uD5;SVGp1EQR4R)L>IBD7Lm(y&>y*i{&FLv 9heYwv zmZL{k>}G8D3Y<&DLwk{f{PXtq_33#yZ@HGwIf2gH2A_siT%IWIlQ}S`*z8Z5qYDr; zi`yZ@P^~p>hG^{~XUuJKOqoyOFArmy#9J-`XL6-1U*QSU&HpJHKkb4y! 2=kL_m!#RIV8CRWZBpoEyJDUV*NdPD zv~zHcWU}qI1s#$dXR+NBv>mWX4h46n7PtIWhuiJ=s_g!(#qGG6r*RSw@<;57L&7=u z+2h4Wf_ROI-J&<8ph2^ume~~ZERz&ew5Co0BzB#8b;ro(B@LR8T>=!rdo(~LMFZ46 z^2KkTdX?i;QblX%(&yCw$;fVLZE)~;kEfjiM8nA~L+^^$i;CcfJ)FyO1uSPi;3MeO zNcn>vZ0M}`g 3p0Qtg zR1_cm(p8U45>a@aC|-vuXcp`8Yl0$nvJ j^8nX z+SSJ=46#cls7KYK6S(i;=z6e^7V_-q1Ss6vPpc;!5e|sU*d_2B5ID~O;eeA?ZsFyA z53s5>)rpfFR;#+g7PCKKvpH-r+YWooMqRcT+s^M$VtWvUcAIU7)rx$y&jj1hPsESK zNwDE^o)@Fg=!WVa^MK`0)GoxhjE4rn8q{NbVNftsT)pjgXCP2xsuXg=N$4F`UsYFd zc(?}MeuG ~&PS2Oi2sUY#iE>nSXc9M(UtTAZ$LY0R zJ}A40T=KQI`2A|X#q0EtT&G@GRYRRlx7(?{MdkDW*(EZmAE~p-L9tKgBVi9elRUy@ zSADdaa(RuRKPyA|fK9qyvPxeu`yC|SVJo+OTeP2PSNx*sdZY1rlf!GFZ-v9^O0&-) z7@$x3jrbk095#-1Lcj0@U>X-nq1}RsC6|XuwlSC2jNvAKK+0!ebAiqaqzQJ}03;_9 ze3Y6XOz;bYCB8Huc4#Z49o3+Z(l3y{B@@hc`UN66SG^8z_R5GYnH_XGS Cc zaojkQ*}8BO^GYo@jTP-SI1)*QX7&X+Q_0_0=t$#@+40RH;Al=d%TlSlJ5$SxS|>$O z6q?+|;mBs)(R4b&DYmXc#<_X8U9_&_Nc+%F#mB`7f=@_tFFvm5)l@Mi5O!{6F+ve0 zW+7*1f#N2Z^3r*c6Cs|I*ttsDP9b}+B0iXimXs!_ahWB$NqyOBVUt6l+A78KRfD*U za-LGy@T{*HCS()rckzm#T|I71DY2+!nfl9A8U19LXg0iNwJTY#XYfKRl~UeQ6Q~V^ z2Y+k