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 @@ + + + + + \ 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 @@ + + + + + \ 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 @@ + + + + + + + \ 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 @@ + + + + + \ 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 @@ + + + + + \ 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