diff --git a/.cursor/rules/rules.mdc b/.cursor/rules/rules.mdc
new file mode 100644
index 0000000..fb6e299
--- /dev/null
+++ b/.cursor/rules/rules.mdc
@@ -0,0 +1,20 @@
+---
+description:
+globs:
+alwaysApply: true
+---
+## 技术栈使用
+- Vue3
+- element-plus
+- piana
+- Vue Router
+- scss
+
+## 编码习惯
+写代码的之前先要看一下目录结构,查看有没有可以复用的组件,如果没用则需要编写代码按照模块拆分成组件使用,让代码可以复用
+
+## 主色调 #0A2463
+
+## 需要图片的时候去/src/assetsimages查看是否有合适的
+
+
diff --git a/.cursor/rules/yw.mdc b/.cursor/rules/yw.mdc
new file mode 100644
index 0000000..dd36119
--- /dev/null
+++ b/.cursor/rules/yw.mdc
@@ -0,0 +1,62 @@
+---
+description:
+globs:
+alwaysApply: false
+---
+
+## 业务结构:了解全局业务
+2.1. 用户注册&登录
+2.1.1. 新用户注册流程
+2.1.2. 已注册用户登录流程
+2.1.3. 服务协议
+2.1.4. 隐私政策
+2.2. 首页-精品推荐
+2.2.1. 列表页
+2.2.2. 公告列表
+2.2.3. 公告详情
+2.2.4. 书本详情页
+2.2.4.1. 功能-互动打赏
+2.2.4.2. 功能-亲密值&排行
+2.2.4.3. 功能-加入书架
+2.2.4.4. 功能-投推荐票
+2.2.4.5. 功能-查看全部章节
+2.2.4.6. 功能-写书评
+2.2.4.7. 功能-回复书评
+2.2.5. 书本阅读页
+2.2.5.1. 功能-加入书架
+2.2.5.2. 功能-查看目录
+2.2.5.3. 功能-目录跳转章节
+2.2.6. 付费流程
+2.3. 分类作品
+2.4. 排行榜
+2.5. 书架
+2.5.1. 功能-删除书本
+2.5.2. 功能-清空书架
+2.6. 消息
+2.7. 作家专区
+2.7.1. 作品管理
+2.7.2. 功能-读者管理
+2.7.2.1. 未设置成就
+2.7.2.2. 首次设置成就
+2.7.2.3. 首次提交审核
+2.7.2.4. 已设置成就
+2.7.2.5. 二次修改
+2.7.2.6. 二次提交审核
+2.7.2.7. 多级成就
+2.7.3. 功能-新建作品
+2.7.4. 去写作
+2.7.4.1. 已发布内容
+2.7.4.1.1. 已发布内容修改
+2.8. 我的模块
+2.8.1. 用户主页
+2.8.2. 个人信息
+2.8.2.1. 豆豆-查看详情(流水记录)
+2.8.2.2. 豆豆-去充值
+2.8.3. 礼物盒
+2.8.3.1. 礼物购买
+2.8.4. 任务中心
+2.8.5. 申请成为创作者
+2.8.6. 钱包流水
+2.8.7. 修改手机号
+
+2.8.8. 退出登录
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..620b729
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+.idea
+package-lock.json
+node_modules
+unpackage
+dist
+.hbuilderx
+.vite
\ No newline at end of file
diff --git a/README.md b/README.md
index 64053eb..6f7318e 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,75 @@
-# novel-front-pc
+# 小说前端PC项目
-小说网站前端代码仓库
\ No newline at end of file
+基于 Vue 3 + Element Plus + Pinia + Vue Router + SCSS 的小说网站前端项目。
+
+## 技术栈
+
+- Vue 3 - 渐进式JavaScript框架
+- Element Plus - 基于Vue 3的组件库
+- Pinia - Vue的状态管理库
+- Vue Router - Vue官方路由管理器
+- SCSS - CSS预处理器
+
+## 项目结构
+
+```
+novel-front-pc/
+├── public/ # 静态资源
+├── src/
+│ ├── api/ # API请求
+│ ├── assets/ # 资源文件(图片、样式等)
+│ │ └── styles/ # 样式文件
+│ ├── components/ # 组件
+│ │ ├── common/ # 通用组件
+│ │ └── layout/ # 布局组件
+│ ├── router/ # 路由配置
+│ ├── store/ # Pinia状态管理
+│ ├── utils/ # 工具函数
+│ ├── views/ # 页面视图
+│ ├── App.vue # 根组件
+│ └── main.js # 入口文件
+├── .gitignore # Git忽略文件
+├── index.html # HTML模板
+├── package.json # 项目依赖
+├── README.md # 项目说明
+└── vite.config.js # Vite配置
+```
+
+## 开发指南
+
+### 安装依赖
+
+```bash
+npm install
+```
+
+### 启动开发服务器
+
+```bash
+npm run dev
+```
+
+### 构建生产版本
+
+```bash
+npm run build
+```
+
+### 预览生产版本
+
+```bash
+npm run serve
+```
+
+## 开发规范
+
+- 组件名使用 PascalCase 命名法
+- 文件夹和文件名使用 kebab-case 命名法
+- 使用 SCSS 编写样式
+- 组件样式使用 scoped 属性限定作用域
+- 使用 Pinia 进行状态管理
+- 使用 Vue Router 进行路由管理
+
+## 组件复用
+
+在编写代码前,请先查看项目目录结构,确认是否有可复用的组件。如果没有可复用的组件,请按照模块进行拆分,使代码可以被复用。
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..5935f47
--- /dev/null
+++ b/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ 小说前端项目
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..5896545
--- /dev/null
+++ b/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "novel-front-pc",
+ "version": "1.0.0",
+ "private": true,
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "serve": "vite preview"
+ },
+ "dependencies": {
+ "axios": "^1.9.0",
+ "element-plus": "^2.3.0",
+ "pinia": "^2.1.0",
+ "vue": "^3.3.0",
+ "vue-router": "^4.2.0"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^4.2.3",
+ "sass": "^1.63.0",
+ "vite": "^4.4.0"
+ }
+}
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..a9681fd
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/api/index.js b/src/api/index.js
new file mode 100644
index 0000000..9abf02e
--- /dev/null
+++ b/src/api/index.js
@@ -0,0 +1,39 @@
+import axios from 'axios';
+
+const api = axios.create({
+ baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
+ timeout: 10000,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+});
+
+// 请求拦截器
+api.interceptors.request.use(
+ config => {
+ const token = localStorage.getItem('token');
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`;
+ }
+ return config;
+ },
+ error => {
+ return Promise.reject(error);
+ }
+);
+
+// 响应拦截器
+api.interceptors.response.use(
+ response => {
+ return response.data;
+ },
+ error => {
+ if (error.response && error.response.status === 401) {
+ // 处理未授权的情况
+ // 可以在这里触发退出登录或跳转到登录页
+ }
+ return Promise.reject(error);
+ }
+);
+
+export default api;
\ No newline at end of file
diff --git a/src/assets/images/.DS_Store b/src/assets/images/.DS_Store
new file mode 100644
index 0000000..8f3f361
Binary files /dev/null and b/src/assets/images/.DS_Store differ
diff --git a/src/assets/images/1.png b/src/assets/images/1.png
new file mode 100644
index 0000000..6751f08
Binary files /dev/null and b/src/assets/images/1.png differ
diff --git a/src/assets/images/2.png b/src/assets/images/2.png
new file mode 100644
index 0000000..35b60b6
Binary files /dev/null and b/src/assets/images/2.png differ
diff --git a/src/assets/images/3.png b/src/assets/images/3.png
new file mode 100644
index 0000000..180fbf9
Binary files /dev/null and b/src/assets/images/3.png differ
diff --git a/src/assets/images/Group 2681.png b/src/assets/images/Group 2681.png
new file mode 100644
index 0000000..a80425c
Binary files /dev/null and b/src/assets/images/Group 2681.png differ
diff --git a/src/assets/images/Group 2878-1.png b/src/assets/images/Group 2878-1.png
new file mode 100644
index 0000000..052d551
Binary files /dev/null and b/src/assets/images/Group 2878-1.png differ
diff --git a/src/assets/images/Group 2878-2.png b/src/assets/images/Group 2878-2.png
new file mode 100644
index 0000000..5150221
Binary files /dev/null and b/src/assets/images/Group 2878-2.png differ
diff --git a/src/assets/images/Group 2878-3.png b/src/assets/images/Group 2878-3.png
new file mode 100644
index 0000000..9e08809
Binary files /dev/null and b/src/assets/images/Group 2878-3.png differ
diff --git a/src/assets/images/Group 2878.png b/src/assets/images/Group 2878.png
new file mode 100644
index 0000000..c2aedd4
Binary files /dev/null and b/src/assets/images/Group 2878.png differ
diff --git a/src/assets/images/home/announcement.png b/src/assets/images/home/announcement.png
new file mode 100644
index 0000000..99b58b8
Binary files /dev/null and b/src/assets/images/home/announcement.png differ
diff --git a/src/assets/images/image-1.png b/src/assets/images/image-1.png
new file mode 100644
index 0000000..644f786
Binary files /dev/null and b/src/assets/images/image-1.png differ
diff --git a/src/assets/images/image-2.png b/src/assets/images/image-2.png
new file mode 100644
index 0000000..f43db67
Binary files /dev/null and b/src/assets/images/image-2.png differ
diff --git a/src/assets/images/image-3.png b/src/assets/images/image-3.png
new file mode 100644
index 0000000..d9f301a
Binary files /dev/null and b/src/assets/images/image-3.png differ
diff --git a/src/assets/images/image-4.png b/src/assets/images/image-4.png
new file mode 100644
index 0000000..4492a01
Binary files /dev/null and b/src/assets/images/image-4.png differ
diff --git a/src/assets/images/image-5.png b/src/assets/images/image-5.png
new file mode 100644
index 0000000..6ce666e
Binary files /dev/null and b/src/assets/images/image-5.png differ
diff --git a/src/assets/images/image-6.png b/src/assets/images/image-6.png
new file mode 100644
index 0000000..7c7f356
Binary files /dev/null and b/src/assets/images/image-6.png differ
diff --git a/src/assets/images/image-7.png b/src/assets/images/image-7.png
new file mode 100644
index 0000000..e0f7c20
Binary files /dev/null and b/src/assets/images/image-7.png differ
diff --git a/src/assets/images/image.png b/src/assets/images/image.png
new file mode 100644
index 0000000..e9f9a4b
Binary files /dev/null and b/src/assets/images/image.png differ
diff --git a/src/assets/images/下.png b/src/assets/images/下.png
new file mode 100644
index 0000000..add8564
Binary files /dev/null and b/src/assets/images/下.png differ
diff --git a/src/assets/images/书城-1.png b/src/assets/images/书城-1.png
new file mode 100644
index 0000000..1be8f59
Binary files /dev/null and b/src/assets/images/书城-1.png differ
diff --git a/src/assets/images/书城-2.png b/src/assets/images/书城-2.png
new file mode 100644
index 0000000..97cb2e0
Binary files /dev/null and b/src/assets/images/书城-2.png differ
diff --git a/src/assets/images/书城.png b/src/assets/images/书城.png
new file mode 100644
index 0000000..6ed8577
Binary files /dev/null and b/src/assets/images/书城.png differ
diff --git a/src/assets/images/书架.png b/src/assets/images/书架.png
new file mode 100644
index 0000000..502b5f3
Binary files /dev/null and b/src/assets/images/书架.png differ
diff --git a/src/assets/images/任务中心.png b/src/assets/images/任务中心.png
new file mode 100644
index 0000000..f460eac
Binary files /dev/null and b/src/assets/images/任务中心.png differ
diff --git a/src/assets/images/修改信息.png b/src/assets/images/修改信息.png
new file mode 100644
index 0000000..85311d6
Binary files /dev/null and b/src/assets/images/修改信息.png differ
diff --git a/src/assets/images/加.png b/src/assets/images/加.png
new file mode 100644
index 0000000..dad33bf
Binary files /dev/null and b/src/assets/images/加.png differ
diff --git a/src/assets/images/加载.png b/src/assets/images/加载.png
new file mode 100644
index 0000000..619e662
Binary files /dev/null and b/src/assets/images/加载.png differ
diff --git a/src/assets/images/取消删除.png b/src/assets/images/取消删除.png
new file mode 100644
index 0000000..e0f98f6
Binary files /dev/null and b/src/assets/images/取消删除.png differ
diff --git a/src/assets/images/右.png b/src/assets/images/右.png
new file mode 100644
index 0000000..2b603ac
Binary files /dev/null and b/src/assets/images/右.png differ
diff --git a/src/assets/images/失败.png b/src/assets/images/失败.png
new file mode 100644
index 0000000..1253759
Binary files /dev/null and b/src/assets/images/失败.png differ
diff --git a/src/assets/images/布丁小说logo.png b/src/assets/images/布丁小说logo.png
new file mode 100644
index 0000000..bf0340d
Binary files /dev/null and b/src/assets/images/布丁小说logo.png differ
diff --git a/src/assets/images/成功.png b/src/assets/images/成功.png
new file mode 100644
index 0000000..ac87a61
Binary files /dev/null and b/src/assets/images/成功.png differ
diff --git a/src/assets/images/我的.png b/src/assets/images/我的.png
new file mode 100644
index 0000000..5f905b6
Binary files /dev/null and b/src/assets/images/我的.png differ
diff --git a/src/assets/images/我的等级.png b/src/assets/images/我的等级.png
new file mode 100644
index 0000000..e818119
Binary files /dev/null and b/src/assets/images/我的等级.png differ
diff --git a/src/assets/images/我的评论.png b/src/assets/images/我的评论.png
new file mode 100644
index 0000000..fcd5c7a
Binary files /dev/null and b/src/assets/images/我的评论.png differ
diff --git a/src/assets/images/投推荐票.png b/src/assets/images/投推荐票.png
new file mode 100644
index 0000000..3b34b2e
Binary files /dev/null and b/src/assets/images/投推荐票.png differ
diff --git a/src/assets/images/推荐票.png b/src/assets/images/推荐票.png
new file mode 100644
index 0000000..1040205
Binary files /dev/null and b/src/assets/images/推荐票.png differ
diff --git a/src/assets/images/申请成为创作者.png b/src/assets/images/申请成为创作者.png
new file mode 100644
index 0000000..cedbf43
Binary files /dev/null and b/src/assets/images/申请成为创作者.png differ
diff --git a/src/assets/images/礼物盒.png b/src/assets/images/礼物盒.png
new file mode 100644
index 0000000..6449fc5
Binary files /dev/null and b/src/assets/images/礼物盒.png differ
diff --git a/src/assets/images/移除书架.png b/src/assets/images/移除书架.png
new file mode 100644
index 0000000..05f05d2
Binary files /dev/null and b/src/assets/images/移除书架.png differ
diff --git a/src/assets/images/移除全部.png b/src/assets/images/移除全部.png
new file mode 100644
index 0000000..2540c27
Binary files /dev/null and b/src/assets/images/移除全部.png differ
diff --git a/src/assets/images/联系客服.png b/src/assets/images/联系客服.png
new file mode 100644
index 0000000..ec31519
Binary files /dev/null and b/src/assets/images/联系客服.png differ
diff --git a/src/assets/images/读者榜单.png b/src/assets/images/读者榜单.png
new file mode 100644
index 0000000..8469bac
Binary files /dev/null and b/src/assets/images/读者榜单.png differ
diff --git a/src/assets/images/退出登录.png b/src/assets/images/退出登录.png
new file mode 100644
index 0000000..348d071
Binary files /dev/null and b/src/assets/images/退出登录.png differ
diff --git a/src/assets/images/钱包流水.png b/src/assets/images/钱包流水.png
new file mode 100644
index 0000000..d99b08c
Binary files /dev/null and b/src/assets/images/钱包流水.png differ
diff --git a/src/assets/images/首页.png b/src/assets/images/首页.png
new file mode 100644
index 0000000..9f70337
Binary files /dev/null and b/src/assets/images/首页.png differ
diff --git a/src/assets/images/默认头像.png b/src/assets/images/默认头像.png
new file mode 100644
index 0000000..65d23e6
Binary files /dev/null and b/src/assets/images/默认头像.png differ
diff --git a/src/assets/styles/global.scss b/src/assets/styles/global.scss
new file mode 100644
index 0000000..c3b06f0
--- /dev/null
+++ b/src/assets/styles/global.scss
@@ -0,0 +1,109 @@
+@use './variables.scss' as vars;
+
+html {
+ font-size: 16px;
+
+ @media screen and (max-width: vars.$lg) {
+ font-size: 15px;
+ }
+
+ @media screen and (max-width: vars.$md) {
+ font-size: 14px;
+ }
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+html,
+body {
+ font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ color: vars.$text-regular;
+}
+
+
+a {
+ text-decoration: none;
+ color: vars.$primary-color;
+}
+
+.page-container {
+ padding: vars.$content-padding;
+}
+
+.flex-center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.text-ellipsis {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.clearfix:after {
+ content: '';
+ display: table;
+ clear: both;
+}
+
+// 全局按钮样式
+.el-button--primary {
+ background-color: vars.$primary-color;
+ border-color: vars.$primary-color;
+
+ &:hover,
+ &:focus {
+ background-color: lighten(vars.$primary-color, 10%);
+ border-color: lighten(vars.$primary-color, 10%);
+ }
+}
+
+.el-button--accent {
+ background-color: vars.$accent-color;
+ border-color: vars.$accent-color;
+ color: #fff;
+
+ &:hover,
+ &:focus {
+ background-color: lighten(vars.$accent-color, 10%);
+ border-color: lighten(vars.$accent-color, 10%);
+ }
+}
+
+// 常用边距
+.mb-10 {
+ margin-bottom: 0.625rem;
+}
+
+.mb-20 {
+ margin-bottom: 1.25rem;
+}
+
+.mt-10 {
+ margin-top: 0.625rem;
+}
+
+.mt-20 {
+ margin-top: 1.25rem;
+}
+
+.ml-10 {
+ margin-left: 0.625rem;
+}
+
+.mr-10 {
+ margin-right: 0.625rem;
+}
+
+// 常用宽度
+.w-100 {
+ width: 100%;
+}
\ No newline at end of file
diff --git a/src/assets/styles/variables.scss b/src/assets/styles/variables.scss
new file mode 100644
index 0000000..d38cd93
--- /dev/null
+++ b/src/assets/styles/variables.scss
@@ -0,0 +1,34 @@
+// 颜色变量
+$primary-color: #0A2463;
+$success-color: #67C23A;
+$warning-color: #E6A23C;
+$danger-color: #F56C6C;
+$info-color: #909399;
+$accent-color: #ef5350;
+
+// 文字颜色
+$text-primary: #303133;
+$text-regular: #606266;
+$text-secondary: #909399;
+$text-placeholder: #C0C4CC;
+
+// 边框颜色
+$border-color-base: #DCDFE6;
+$border-color-light: #E4E7ED;
+$border-color-lighter: #EBEEF5;
+$border-color-extra-light: #F2F6FC;
+
+// 背景颜色
+$background-color-base: #F5F7FA;
+
+// 布局相关
+$header-height: 3.75rem; // 60px
+$sidebar-width: 15rem; // 240px
+$content-padding: 1.25rem; // 20px
+
+// 响应式断点
+$xs: 576px;
+$sm: 768px;
+$md: 992px;
+$lg: 1200px;
+$xl: 1920px;
\ No newline at end of file
diff --git a/src/components/auth/AuthProvider.vue b/src/components/auth/AuthProvider.vue
new file mode 100644
index 0000000..f589bd7
--- /dev/null
+++ b/src/components/auth/AuthProvider.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/auth/LoginRegisterModal.vue b/src/components/auth/LoginRegisterModal.vue
new file mode 100644
index 0000000..04b3800
--- /dev/null
+++ b/src/components/auth/LoginRegisterModal.vue
@@ -0,0 +1,324 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/common/BookCard.vue b/src/components/common/BookCard.vue
new file mode 100644
index 0000000..7d86994
--- /dev/null
+++ b/src/components/common/BookCard.vue
@@ -0,0 +1,139 @@
+
+
+
+

+
+
+
{{ book.title }}
+
作者:{{ book.author }}
+
{{ book.description }}
+
+ {{ book.status }}
+ {{ book.readCount }}人在读
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/layout/components/BackToTop.vue b/src/layout/components/BackToTop.vue
new file mode 100644
index 0000000..36c4165
--- /dev/null
+++ b/src/layout/components/BackToTop.vue
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/layout/components/Breadcrumb.vue b/src/layout/components/Breadcrumb.vue
new file mode 100644
index 0000000..990ab1b
--- /dev/null
+++ b/src/layout/components/Breadcrumb.vue
@@ -0,0 +1,91 @@
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/layout/index.vue b/src/layout/index.vue
new file mode 100644
index 0000000..12cf3a5
--- /dev/null
+++ b/src/layout/index.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/layout/Footer.vue b/src/layout/layout/Footer.vue
new file mode 100644
index 0000000..f5e6d51
--- /dev/null
+++ b/src/layout/layout/Footer.vue
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/layout/layout/Header.vue b/src/layout/layout/Header.vue
new file mode 100644
index 0000000..c9add71
--- /dev/null
+++ b/src/layout/layout/Header.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..13bc171
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,26 @@
+import { createApp } from 'vue';
+import ElementPlus from 'element-plus';
+import 'element-plus/dist/index.css';
+import { createPinia } from 'pinia';
+import App from './App.vue';
+import router from './router';
+import { useMainStore } from './store';
+
+// 导入全局样式
+import './assets/styles/global.scss';
+
+const app = createApp(App);
+const pinia = createPinia();
+
+app.use(ElementPlus);
+app.use(pinia);
+app.use(router);
+
+// 初始化身份验证状态
+const store = useMainStore();
+store.initializeAuth();
+
+// 全局挂载pinia,用于路由守卫
+window.$pinia = pinia;
+
+app.mount('#app');
\ No newline at end of file
diff --git a/src/router/index.js b/src/router/index.js
new file mode 100644
index 0000000..48b3421
--- /dev/null
+++ b/src/router/index.js
@@ -0,0 +1,53 @@
+import { createRouter, createWebHistory } from 'vue-router';
+
+
+import layout from '../layout/index.vue';
+
+const routes = [
+ {
+ path: '/',
+ name: 'layout',
+ component: layout,
+ children: [
+ {
+ path: '',
+ name: 'Home',
+ component: () => import('../views/home/Home.vue')
+ },
+ {
+ path: 'book/:id',
+ name: 'BookDetail',
+ component: () => import('../views/book/index.vue')
+ },
+ {
+ path: 'book/:id/chapter/:chapterId',
+ name: 'ChapterDetail',
+ component: () => import('../views/book/chapter.vue')
+ }
+ ]
+ },
+ {
+ path: '/:pathMatch(.*)*',
+ name: 'NotFound',
+ component: () => import('../views/NotFound.vue')
+ }
+];
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes
+});
+
+// 全局路由守卫
+router.beforeEach((to, from, next) => {
+ const store = window.$pinia?.state.value?.main;
+ const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
+
+ if (requiresAuth && (!store || !store.isLoggedIn)) {
+ next({ path: '/login', query: { redirect: to.fullPath } });
+ } else {
+ next();
+ }
+});
+
+export default router;
\ No newline at end of file
diff --git a/src/store/index.js b/src/store/index.js
new file mode 100644
index 0000000..c522fbc
--- /dev/null
+++ b/src/store/index.js
@@ -0,0 +1,83 @@
+import { defineStore } from 'pinia';
+
+export const useMainStore = defineStore('main', {
+ state: () => ({
+ user: null,
+ isLoggedIn: false,
+ token: null
+ }),
+
+ getters: {
+ isAuthenticated: (state) => state.isLoggedIn && state.user !== null
+ },
+
+ actions: {
+ async login(loginData) {
+ try {
+ // 模拟API调用,实际项目中这里应该调用后端API
+ // 这里模拟一个异步操作
+ await new Promise(resolve => setTimeout(resolve, 1000));
+
+ // 模拟登录成功响应
+ const userData = {
+ id: 'user_' + Date.now(),
+ name: '用户' + loginData.phone.substring(loginData.phone.length - 4),
+ phone: loginData.phone,
+ avatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
+ };
+
+ this.user = userData;
+ this.isLoggedIn = true;
+ this.token = 'mock_token_' + Date.now();
+
+ // 保存到本地存储,使登录状态持久化
+ localStorage.setItem('user', JSON.stringify(userData));
+ localStorage.setItem('token', this.token);
+
+ return userData;
+ } catch (error) {
+ console.error('登录失败:', error);
+ throw new Error('登录失败,请稍后重试');
+ }
+ },
+
+ async register(registerData) {
+ try {
+ // 模拟API调用,实际项目中这里应该调用后端API
+ await new Promise(resolve => setTimeout(resolve, 1000));
+
+ // 模拟注册成功,自动登录
+ return this.login(registerData);
+ } catch (error) {
+ console.error('注册失败:', error);
+ throw new Error('注册失败,请稍后重试');
+ }
+ },
+
+ logout() {
+ this.user = null;
+ this.isLoggedIn = false;
+ this.token = null;
+
+ // 清除本地存储
+ localStorage.removeItem('user');
+ localStorage.removeItem('token');
+ },
+
+ // 初始化,从本地存储恢复登录状态
+ initializeAuth() {
+ const userData = localStorage.getItem('user');
+ const token = localStorage.getItem('token');
+
+ if (userData && token) {
+ try {
+ this.user = JSON.parse(userData);
+ this.token = token;
+ this.isLoggedIn = true;
+ } catch (e) {
+ this.logout();
+ }
+ }
+ }
+ }
+});
\ No newline at end of file
diff --git a/src/utils/request.js b/src/utils/request.js
new file mode 100644
index 0000000..738d873
--- /dev/null
+++ b/src/utils/request.js
@@ -0,0 +1,69 @@
+import api from '@/api';
+
+/**
+ * 获取通用请求配置选项
+ * @param {object} options - 请求配置选项
+ * @returns {object} - 处理后的请求配置
+ */
+const getRequestOptions = (options = {}) => {
+ return {
+ ...options
+ };
+};
+
+/**
+ * GET请求
+ * @param {string} url - 请求地址
+ * @param {object} params - 请求参数
+ * @param {object} options - 请求配置选项
+ * @returns {Promise} - 请求Promise对象
+ */
+export const get = (url, params = {}, options = {}) => {
+ return api.get(url, {
+ params,
+ ...getRequestOptions(options)
+ });
+};
+
+/**
+ * POST请求
+ * @param {string} url - 请求地址
+ * @param {object} data - 请求数据
+ * @param {object} options - 请求配置选项
+ * @returns {Promise} - 请求Promise对象
+ */
+export const post = (url, data = {}, options = {}) => {
+ return api.post(url, data, getRequestOptions(options));
+};
+
+/**
+ * PUT请求
+ * @param {string} url - 请求地址
+ * @param {object} data - 请求数据
+ * @param {object} options - 请求配置选项
+ * @returns {Promise} - 请求Promise对象
+ */
+export const put = (url, data = {}, options = {}) => {
+ return api.put(url, data, getRequestOptions(options));
+};
+
+/**
+ * DELETE请求
+ * @param {string} url - 请求地址
+ * @param {object} data - 请求数据
+ * @param {object} options - 请求配置选项
+ * @returns {Promise} - 请求Promise对象
+ */
+export const del = (url, data = {}, options = {}) => {
+ return api.delete(url, {
+ data,
+ ...getRequestOptions(options)
+ });
+};
+
+export default {
+ get,
+ post,
+ put,
+ del
+};
\ No newline at end of file
diff --git a/src/views/NotFound.vue b/src/views/NotFound.vue
new file mode 100644
index 0000000..1bbed94
--- /dev/null
+++ b/src/views/NotFound.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/book/chapter.vue b/src/views/book/chapter.vue
new file mode 100644
index 0000000..4561973
--- /dev/null
+++ b/src/views/book/chapter.vue
@@ -0,0 +1,352 @@
+
+
+
+
+
+
{{ chapter.title }}
+
+
+ 上一章
+ 目录
+ 下一章
+
+
+
+
+
+ 上一章
+ 目录
+ 下一章
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/book/index.vue b/src/views/book/index.vue
new file mode 100644
index 0000000..1d16aa5
--- /dev/null
+++ b/src/views/book/index.vue
@@ -0,0 +1,576 @@
+
+
+
+
+
+
+
![]()
+
+
+
{{ book.title }}
+
+
+
+ 加入书架
+ 立即阅读
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ chapter.title }}
+
新
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/home/Home.vue b/src/views/home/Home.vue
new file mode 100644
index 0000000..735df23
--- /dev/null
+++ b/src/views/home/Home.vue
@@ -0,0 +1,483 @@
+
+
+
+
+
+
+
+
+
+
+
{{ banner.title }}
+
{{ banner.desc }}
+
+
+
+
+
+
+
+
+
+
+
+
{{ notice.typeText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..f98c145
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,16 @@
+import { defineConfig } from 'vite';
+import vue from '@vitejs/plugin-vue';
+import path from 'path';
+
+export default defineConfig({
+ plugins: [vue()],
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, 'src')
+ }
+ },
+ server: {
+ port: 3000,
+ open: true
+ }
+});
\ No newline at end of file
发表书评
+