You've already forked SmartisanNote.Remake
future #11
33
IFLOW.md
33
IFLOW.md
@@ -14,6 +14,8 @@
|
|||||||
* **PWA 支持**: vite-plugin-pwa
|
* **PWA 支持**: vite-plugin-pwa
|
||||||
* **本地存储**: IndexedDB (通过 `src/utils/indexedDBStorage.js` 封装)
|
* **本地存储**: IndexedDB (通过 `src/utils/indexedDBStorage.js` 封装)
|
||||||
* **CSS 预处理器**: Less
|
* **CSS 预处理器**: Less
|
||||||
|
* **动画库**: @oku-ui/motion
|
||||||
|
* **拖拽库**: vue-draggable-plus
|
||||||
|
|
||||||
## 项目结构
|
## 项目结构
|
||||||
|
|
||||||
@@ -21,17 +23,41 @@
|
|||||||
.
|
.
|
||||||
├── android/ # Capacitor Android 项目文件
|
├── android/ # Capacitor Android 项目文件
|
||||||
├── public/ # 静态资源目录 (图标等)
|
├── public/ # 静态资源目录 (图标等)
|
||||||
|
│ ├── assets/ # 应用资源文件
|
||||||
|
│ │ └── icons/ # 图标文件
|
||||||
|
│ │ ├── drawable-xxhdpi/ # Android 图标资源
|
||||||
|
│ │ └── drawable-xxxhdpi/ # Android 图标资源
|
||||||
|
│ └── icons/ # PWA 图标
|
||||||
|
│ ├── icon-192.png
|
||||||
|
│ └── icon-512.png
|
||||||
├── src/ # 源代码目录
|
├── src/ # 源代码目录
|
||||||
│ ├── App.vue # 根组件
|
│ ├── App.vue # 根组件
|
||||||
│ ├── main.js # 应用入口文件
|
│ ├── main.js # 应用入口文件
|
||||||
│ ├── common/ # 通用样式
|
│ ├── common/ # 通用样式
|
||||||
|
│ │ └── base.css # 基础样式文件
|
||||||
│ ├── components/ # 可复用的 UI 组件
|
│ ├── components/ # 可复用的 UI 组件
|
||||||
|
│ │ ├── FolderItem.vue # 文件夹项组件
|
||||||
|
│ │ ├── FolderManage.vue # 文件夹管理组件
|
||||||
|
│ │ ├── Header.vue # 头部组件
|
||||||
|
│ │ ├── Modal.vue # 模态框组件
|
||||||
|
│ │ ├── NoteItem.vue # 便签项组件
|
||||||
|
│ │ ├── RichTextEditor.vue # 富文本编辑器组件
|
||||||
|
│ │ ├── Search.vue # 搜索组件
|
||||||
|
│ │ ├── SettingGroup.vue # 设置组组件
|
||||||
|
│ │ └── SwitchButton.vue # 开关按钮组件
|
||||||
│ ├── pages/ # 页面组件
|
│ ├── pages/ # 页面组件
|
||||||
|
│ │ ├── FolderPage.vue # 文件夹页面
|
||||||
|
│ │ ├── NoteEditorPage.vue # 便签编辑页面
|
||||||
|
│ │ ├── NoteListPage.vue # 便签列表页面
|
||||||
|
│ │ └── SettingsPage.vue # 设置页面
|
||||||
│ ├── stores/ # Pinia 状态管理
|
│ ├── stores/ # Pinia 状态管理
|
||||||
|
│ │ ├── useAppStore.js # 应用状态管理
|
||||||
|
│ │ └── useAppStore.test.js # 应用状态管理测试
|
||||||
│ └── utils/ # 工具函数
|
│ └── utils/ # 工具函数
|
||||||
|
│ ├── dateUtils.js # 日期工具函数
|
||||||
|
│ └── indexedDBStorage.js # IndexedDB 存储封装
|
||||||
├── index.html # 应用入口 HTML 文件
|
├── index.html # 应用入口 HTML 文件
|
||||||
├── .nvmdrc # node.js 版本
|
├── .nvmdrc # node.js 版本
|
||||||
├── update.txt # 更新日志
|
|
||||||
├── package.json # 项目依赖和脚本
|
├── package.json # 项目依赖和脚本
|
||||||
├── vite.config.js # Vite 配置文件
|
├── vite.config.js # Vite 配置文件
|
||||||
└── capacitor.config.json # Capacitor 配置文件
|
└── capacitor.config.json # Capacitor 配置文件
|
||||||
@@ -46,6 +72,9 @@
|
|||||||
* **多种排序方式**: 按更新时间、标题、星标状态排序。
|
* **多种排序方式**: 按更新时间、标题、星标状态排序。
|
||||||
* **PWA 支持**: 可安装为独立应用,支持离线使用。
|
* **PWA 支持**: 可安装为独立应用,支持离线使用。
|
||||||
* **本地存储**: 所有数据存储在浏览器的 `IndexedDB` 中。
|
* **本地存储**: 所有数据存储在浏览器的 `IndexedDB` 中。
|
||||||
|
* **富文本编辑**: 支持标题、待办事项、列表、加粗、引用、图片等多种格式。
|
||||||
|
* **动画效果**: 使用 Oku Motion 实现流畅的动画效果。
|
||||||
|
* **拖拽排序**: 支持图片拖拽排序。
|
||||||
* **深色模式**: (计划中) 支持切换深色/浅色主题。
|
* **深色模式**: (计划中) 支持切换深色/浅色主题。
|
||||||
* **云同步**: (计划中) 支持多设备间数据同步。
|
* **云同步**: (计划中) 支持多设备间数据同步。
|
||||||
|
|
||||||
@@ -123,6 +152,8 @@ npm run android
|
|||||||
* **CSS 命名**: 使用 BEM 命名规范,部分使用原子化 CSS 类名(以 `code-fun-` 开头)
|
* **CSS 命名**: 使用 BEM 命名规范,部分使用原子化 CSS 类名(以 `code-fun-` 开头)
|
||||||
* **响应式设计**: 使用 viewport 单位 (vw/vh) 和 CSS 变量实现响应式布局
|
* **响应式设计**: 使用 viewport 单位 (vw/vh) 和 CSS 变量实现响应式布局
|
||||||
* **图标**: 使用 PNG 图片作为图标,存储在 `public/assets/icons/` 目录下
|
* **图标**: 使用 PNG 图片作为图标,存储在 `public/assets/icons/` 目录下
|
||||||
|
* **动画**: 使用 Oku Motion 实现动画效果
|
||||||
|
* **拖拽**: 使用 vue-draggable-plus 实现拖拽功能
|
||||||
|
|
||||||
### 命名规范
|
### 命名规范
|
||||||
|
|
||||||
|
|||||||
109
README.md
Normal file
109
README.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# 锤子便签(重制版)
|
||||||
|
|
||||||
|
这是一个基于 Vue 3、Vite 和 Pinia 的移动端现代化 Web 应用,旨在重现并改进经典的锤子便签应用体验。该项目采用 PWA(渐进式 Web 应用)技术,支持离线使用和安装到主屏幕。
|
||||||
|
|
||||||
|
## 主要特性
|
||||||
|
|
||||||
|
- **便签管理**: 创建、编辑、删除、置顶、加星便签
|
||||||
|
- **文件夹管理**: 将便签分类到不同的文件夹中
|
||||||
|
- **搜索功能**: 按标题或内容搜索便签
|
||||||
|
- **回收站**: 临时存储已删除的便签,支持彻底删除
|
||||||
|
- **多种排序方式**: 按更新时间、标题、星标状态排序
|
||||||
|
- **PWA 支持**: 可安装为独立应用,支持离线使用
|
||||||
|
- **本地存储**: 所有数据存储在浏览器的 IndexedDB 中
|
||||||
|
- **富文本编辑**: 支持标题、待办事项、列表、加粗、引用、图片等多种格式
|
||||||
|
- **动画效果**: 使用 Oku Motion 实现流畅的动画效果
|
||||||
|
- **拖拽排序**: 支持图片拖拽排序
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- **框架**: Vue 3 (Composition API)
|
||||||
|
- **构建工具**: Vite
|
||||||
|
- **状态管理**: Pinia
|
||||||
|
- **路由**: Vue Router
|
||||||
|
- **UI 组件库**: Ionic Vue (部分使用)
|
||||||
|
- **PWA 支持**: vite-plugin-pwa
|
||||||
|
- **本地存储**: IndexedDB (通过 `src/utils/indexedDBStorage.js` 封装)
|
||||||
|
- **CSS 预处理器**: Less
|
||||||
|
- **动画库**: @oku-ui/motion
|
||||||
|
- **拖拽库**: vue-draggable-plus
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── android/ # Capacitor Android 项目文件
|
||||||
|
├── public/ # 静态资源目录 (图标等)
|
||||||
|
├── src/ # 源代码目录
|
||||||
|
│ ├── App.vue # 根组件
|
||||||
|
│ ├── main.js # 应用入口文件
|
||||||
|
│ ├── common/ # 通用样式
|
||||||
|
│ ├── components/ # 可复用的 UI 组件
|
||||||
|
│ ├── pages/ # 页面组件
|
||||||
|
│ ├── stores/ # Pinia 状态管理
|
||||||
|
│ └── utils/ # 工具函数
|
||||||
|
├── index.html # 应用入口 HTML 文件
|
||||||
|
├── package.json # 项目依赖和脚本
|
||||||
|
├── vite.config.js # Vite 配置文件
|
||||||
|
└── capacitor.config.json # Capacitor 配置文件
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发与构建
|
||||||
|
|
||||||
|
### 前置条件
|
||||||
|
|
||||||
|
确保已安装 Node.js (>=14) 和 npm。
|
||||||
|
|
||||||
|
### 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 开发
|
||||||
|
|
||||||
|
启动开发服务器:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
这将在 `http://localhost:3000` 启动应用。
|
||||||
|
|
||||||
|
### 构建
|
||||||
|
|
||||||
|
构建标准 Web 应用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
构建 PWA 应用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build:pwa
|
||||||
|
```
|
||||||
|
|
||||||
|
构建所有版本 (标准 + PWA):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build:all
|
||||||
|
```
|
||||||
|
|
||||||
|
### 部署 PWA
|
||||||
|
|
||||||
|
构建 PWA 并上传到服务器:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run deploy:pwa
|
||||||
|
```
|
||||||
|
|
||||||
|
这将执行 `vite build --mode pwa` 并运行 `upload-pwa.js` 脚本。
|
||||||
|
|
||||||
|
### Android 应用
|
||||||
|
|
||||||
|
运行 Android 应用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run android
|
||||||
|
```
|
||||||
247
package-lock.json
generated
247
package-lock.json
generated
@@ -14,6 +14,8 @@
|
|||||||
"@capacitor/core": "^5.7.2",
|
"@capacitor/core": "^5.7.2",
|
||||||
"@capacitor/ios": "^5.7.2",
|
"@capacitor/ios": "^5.7.2",
|
||||||
"@ionic/vue": "^8.7.6",
|
"@ionic/vue": "^8.7.6",
|
||||||
|
"@motionone/vue": "^10.16.4",
|
||||||
|
"@oku-ui/motion": "^0.4.3",
|
||||||
"@vue/cli-service": "^5.0.9",
|
"@vue/cli-service": "^5.0.9",
|
||||||
"@vue/compiler-sfc": "^3.5.22",
|
"@vue/compiler-sfc": "^3.5.22",
|
||||||
"basic-ftp": "^5.0.5",
|
"basic-ftp": "^5.0.5",
|
||||||
@@ -2125,6 +2127,63 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@floating-ui/core": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/utils": "^0.2.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/dom": {
|
||||||
|
"version": "1.7.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.4.tgz",
|
||||||
|
"integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/core": "^1.7.3",
|
||||||
|
"@floating-ui/utils": "^0.2.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/utils": {
|
||||||
|
"version": "0.2.10",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz",
|
||||||
|
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/vue": {
|
||||||
|
"version": "1.1.9",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@floating-ui/vue/-/vue-1.1.9.tgz",
|
||||||
|
"integrity": "sha512-BfNqNW6KA83Nexspgb9DZuz578R7HT8MZw1CfK9I6Ah4QReNWEJsXWHN+SdmOVLNGmTPDi+fDT535Df5PzMLbQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/dom": "^1.7.4",
|
||||||
|
"@floating-ui/utils": "^0.2.10",
|
||||||
|
"vue-demi": ">=0.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@floating-ui/vue/node_modules/vue-demi": {
|
||||||
|
"version": "0.14.10",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
|
||||||
|
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||||
|
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0-rc.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@hapi/hoek": {
|
"node_modules/@hapi/hoek": {
|
||||||
"version": "9.3.0",
|
"version": "9.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
|
||||||
@@ -2465,6 +2524,74 @@
|
|||||||
"integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==",
|
"integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@motionone/animation": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@motionone/animation/-/animation-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/easing": "^10.18.0",
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"@motionone/utils": "^10.18.0",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/dom": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@motionone/dom/-/dom-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/animation": "^10.18.0",
|
||||||
|
"@motionone/generators": "^10.18.0",
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"@motionone/utils": "^10.18.0",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/easing": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@motionone/easing/-/easing-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/utils": "^10.18.0",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/generators": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@motionone/generators/-/generators-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"@motionone/utils": "^10.18.0",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/types": {
|
||||||
|
"version": "10.17.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@motionone/types/-/types-10.17.1.tgz",
|
||||||
|
"integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A=="
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/utils": {
|
||||||
|
"version": "10.18.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@motionone/utils/-/utils-10.18.0.tgz",
|
||||||
|
"integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/types": "^10.17.1",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@motionone/vue": {
|
||||||
|
"version": "10.16.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@motionone/vue/-/vue-10.16.4.tgz",
|
||||||
|
"integrity": "sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg==",
|
||||||
|
"deprecated": "Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion",
|
||||||
|
"dependencies": {
|
||||||
|
"@motionone/dom": "^10.16.4",
|
||||||
|
"tslib": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@node-ipc/js-queue": {
|
"node_modules/@node-ipc/js-queue": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz",
|
||||||
@@ -2512,6 +2639,41 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@oku-ui/motion": {
|
||||||
|
"version": "0.4.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@oku-ui/motion/-/motion-0.4.3.tgz",
|
||||||
|
"integrity": "sha512-Z4fd1BaxfwhEImmsYp5szZ3YNATG64l6cOn8Nia3KaUwYNPhIbfM2wME5cnEFe3JLh1kBaANsJgcJZT1ZSI+mw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@oku-ui/primitives": "^0.7.5",
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"framer-motion": "^11.11.17",
|
||||||
|
"hey-listen": "^1.0.8",
|
||||||
|
"motion": "^11.11.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/productdevbook"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/shared": "^3.4.31"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oku-ui/primitives": {
|
||||||
|
"version": "0.7.8",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@oku-ui/primitives/-/primitives-0.7.8.tgz",
|
||||||
|
"integrity": "sha512-Q0QcyZ23jzx84p6I5PK3BS1Szs9bmSTD4OcOjRq5pqw8W9YBWIXHiDpShvW3B2pKofjNn0RtNund5EZwF1GCVw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/dom": "^1.6.12",
|
||||||
|
"@floating-ui/utils": "^0.2.8",
|
||||||
|
"@floating-ui/vue": "^1.1.5",
|
||||||
|
"aria-hidden": "^1.2.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/productdevbook"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": ">= 3.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@polka/url": {
|
"node_modules/@polka/url": {
|
||||||
"version": "1.0.0-next.29",
|
"version": "1.0.0-next.29",
|
||||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
|
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
|
||||||
@@ -4149,6 +4311,17 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/aria-hidden": {
|
||||||
|
"version": "1.2.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/aria-hidden/-/aria-hidden-1.2.6.tgz",
|
||||||
|
"integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/array-buffer-byte-length": {
|
"node_modules/array-buffer-byte-length": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
|
||||||
@@ -5767,6 +5940,11 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/defu": {
|
||||||
|
"version": "6.1.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/defu/-/defu-6.1.4.tgz",
|
||||||
|
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
@@ -6711,6 +6889,32 @@
|
|||||||
"url": "https://github.com/sponsors/rawify"
|
"url": "https://github.com/sponsors/rawify"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "11.18.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/framer-motion/-/framer-motion-11.18.2.tgz",
|
||||||
|
"integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^11.18.1",
|
||||||
|
"motion-utils": "^11.18.1",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fresh": {
|
"node_modules/fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
@@ -7137,6 +7341,11 @@
|
|||||||
"he": "bin/he"
|
"he": "bin/he"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hey-listen": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmmirror.com/hey-listen/-/hey-listen-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
|
||||||
|
},
|
||||||
"node_modules/highlight.js": {
|
"node_modules/highlight.js": {
|
||||||
"version": "10.7.3",
|
"version": "10.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
|
||||||
@@ -8950,6 +9159,44 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion": {
|
||||||
|
"version": "11.18.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/motion/-/motion-11.18.2.tgz",
|
||||||
|
"integrity": "sha512-JLjvFDuFr42NFtcVoMAyC2sEjnpA8xpy6qWPyzQvCloznAyQ8FIXioxWfHiLtgYhoVpfUqSWpn1h9++skj9+Wg==",
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^11.18.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "11.18.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/motion-dom/-/motion-dom-11.18.1.tgz",
|
||||||
|
"integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^11.18.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "11.18.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/motion-utils/-/motion-utils-11.18.1.tgz",
|
||||||
|
"integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA=="
|
||||||
|
},
|
||||||
"node_modules/mrmime": {
|
"node_modules/mrmime": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"@capacitor/core": "^5.7.2",
|
"@capacitor/core": "^5.7.2",
|
||||||
"@capacitor/ios": "^5.7.2",
|
"@capacitor/ios": "^5.7.2",
|
||||||
"@ionic/vue": "^8.7.6",
|
"@ionic/vue": "^8.7.6",
|
||||||
|
"@oku-ui/motion": "^0.4.3",
|
||||||
"@vue/cli-service": "^5.0.9",
|
"@vue/cli-service": "^5.0.9",
|
||||||
"@vue/compiler-sfc": "^3.5.22",
|
"@vue/compiler-sfc": "^3.5.22",
|
||||||
"basic-ftp": "^5.0.5",
|
"basic-ftp": "^5.0.5",
|
||||||
|
|||||||
174
src/App.vue
174
src/App.vue
@@ -1,7 +1,179 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-view />
|
<div class="app-container">
|
||||||
|
<!-- 设置页面背景(列表页) -->
|
||||||
|
<NoteListPage v-show="showBackgroundPage" class="background-page" />
|
||||||
|
|
||||||
|
<!-- 普通页面过渡效果(不包括设置页面) -->
|
||||||
|
<template v-if="!isSettingsRoute">
|
||||||
|
<router-view v-slot="{ Component, route }">
|
||||||
|
<transition :name="transitionName">
|
||||||
|
<component :is="Component" :key="route.path" />
|
||||||
|
</transition>
|
||||||
|
</router-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 设置页面 -->
|
||||||
|
<transition
|
||||||
|
name="settings-slide"
|
||||||
|
v-show="isSettingsRoute"
|
||||||
|
appear>
|
||||||
|
<SettingsPage class="setting-page" />
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref, watch, computed } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
import '@/common/base.css'
|
import '@/common/base.css'
|
||||||
|
|
||||||
|
// 导入页面组件
|
||||||
|
import NoteListPage from './pages/NoteListPage.vue'
|
||||||
|
import SettingsPage from './pages/SettingsPage.vue'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const transitionName = ref('slide-left')
|
||||||
|
|
||||||
|
// 计算是否为设置页面路由
|
||||||
|
const isSettingsRoute = computed(() => {
|
||||||
|
return route.path === '/settings'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算是否需要显示背景页面(仅在设置页面时显示)
|
||||||
|
const showBackgroundPage = computed(() => {
|
||||||
|
return route.path === '/settings'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听路由变化,动态设置过渡动画方向
|
||||||
|
watch(
|
||||||
|
() => route.path,
|
||||||
|
(toPath, fromPath) => {
|
||||||
|
// 特殊处理:从编辑页返回列表页的情况
|
||||||
|
if ((fromPath.startsWith('/editor') || fromPath.startsWith('/notes/')) && toPath === '/notes') {
|
||||||
|
transitionName.value = 'slide-right'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断导航方向
|
||||||
|
const toDepth = toPath.split('/').length
|
||||||
|
const fromDepth = fromPath.split('/').length
|
||||||
|
|
||||||
|
// 如果是进入更深的页面(如从列表页进入编辑页),使用左滑动画
|
||||||
|
if (toDepth > fromDepth) {
|
||||||
|
transitionName.value = 'slide-left'
|
||||||
|
}
|
||||||
|
// 如果是返回上层页面(如从编辑页返回列表页),使用右滑动画
|
||||||
|
else if (toDepth < fromDepth) {
|
||||||
|
transitionName.value = 'slide-right'
|
||||||
|
}
|
||||||
|
// 同级页面切换使用默认的左滑动画
|
||||||
|
else {
|
||||||
|
transitionName.value = 'slide-left'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 无额外处理函数
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.app-container {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #f5f5f5; // 设置默认背景色,防止闪烁
|
||||||
|
}
|
||||||
|
|
||||||
|
// 背景页面样式
|
||||||
|
.background-page {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-page {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 左滑进入(从右到左)
|
||||||
|
.slide-left-enter-active,
|
||||||
|
.slide-left-leave-active {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-left-enter-from {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-left-leave-to {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-left-enter-to,
|
||||||
|
.slide-left-leave-from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右滑进入(从左到右)
|
||||||
|
.slide-right-enter-active,
|
||||||
|
.slide-right-leave-active {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-right-enter-from {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-right-leave-to {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-right-enter-to,
|
||||||
|
.slide-right-leave-from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置页面滑入滑出效果
|
||||||
|
.settings-slide-enter-active,
|
||||||
|
.settings-slide-leave-active {
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-slide-enter-from {
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-slide-leave-to {
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-slide-enter-to,
|
||||||
|
.settings-slide-leave-from {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
13
src/main.js
13
src/main.js
@@ -1,6 +1,7 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
|
import { motionPlugin } from '@oku-ui/motion'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
|
||||||
// 导入页面组件
|
// 导入页面组件
|
||||||
@@ -32,14 +33,14 @@ const routes = [
|
|||||||
// 文件夹管理页面路由
|
// 文件夹管理页面路由
|
||||||
{ path: '/folders', component: FolderPage },
|
{ path: '/folders', component: FolderPage },
|
||||||
// 设置页面路由
|
// 设置页面路由
|
||||||
{ path: '/settings', component: SettingsPage }
|
{ path: '/settings', component: SettingsPage },
|
||||||
]
|
]
|
||||||
|
|
||||||
// 创建路由实例
|
// 创建路由实例
|
||||||
// 使用Hash模式以支持静态文件部署
|
// 使用Hash模式以支持静态文件部署
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
routes
|
routes,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 创建并挂载Vue应用实例
|
// 创建并挂载Vue应用实例
|
||||||
@@ -47,9 +48,11 @@ const router = createRouter({
|
|||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
// 初始化数据库
|
// 初始化数据库
|
||||||
initDB().then(() => {
|
initDB()
|
||||||
|
.then(() => {
|
||||||
console.log('数据库初始化成功')
|
console.log('数据库初始化成功')
|
||||||
}).catch(error => {
|
})
|
||||||
|
.catch(error => {
|
||||||
console.error('数据库初始化失败:', error)
|
console.error('数据库初始化失败:', error)
|
||||||
// 即使数据库初始化失败,也继续启动应用
|
// 即使数据库初始化失败,也继续启动应用
|
||||||
// 这样可以确保应用在没有IndexedDB支持的环境中仍然可以运行
|
// 这样可以确保应用在没有IndexedDB支持的环境中仍然可以运行
|
||||||
@@ -59,5 +62,7 @@ initDB().then(() => {
|
|||||||
app.use(createPinia())
|
app.use(createPinia())
|
||||||
// 使用Vue Router进行路由管理
|
// 使用Vue Router进行路由管理
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
// 使用Oku Motion插件
|
||||||
|
app.use(motionPlugin)
|
||||||
// 挂载应用到DOM元素
|
// 挂载应用到DOM元素
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
@@ -29,6 +29,7 @@ import { useAppStore } from '../stores/useAppStore'
|
|||||||
import Header from '../components/Header.vue'
|
import Header from '../components/Header.vue'
|
||||||
import RichTextEditor from '../components/RichTextEditor.vue'
|
import RichTextEditor from '../components/RichTextEditor.vue'
|
||||||
import { formatNoteEditorDate } from '../utils/dateUtils'
|
import { formatNoteEditorDate } from '../utils/dateUtils'
|
||||||
|
import { IonPage } from '@ionic/vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import { useAppStore } from '../stores/useAppStore'
|
|||||||
import Header from '../components/Header.vue'
|
import Header from '../components/Header.vue'
|
||||||
import SettingGroup from '../components/SettingGroup.vue'
|
import SettingGroup from '../components/SettingGroup.vue'
|
||||||
import SwitchButton from '../components/SwitchButton.vue'
|
import SwitchButton from '../components/SwitchButton.vue'
|
||||||
|
import { IonPage } from '@ionic/vue'
|
||||||
|
|
||||||
const store = useAppStore()
|
const store = useAppStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -52,7 +53,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 切换云同步设置
|
// 切换云同步设置
|
||||||
// 调用store中的方法更新云同步状态
|
// 调用store中的方法更新云同步状态
|
||||||
const toggleCloudSync = (value) => {
|
const toggleCloudSync = value => {
|
||||||
store.toggleCloudSync()
|
store.toggleCloudSync()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user