├── static └── .gitkeep ├── config ├── prod.env.js ├── dev.env.js └── index.js ├── src ├── assets │ ├── logo.png │ ├── images │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ └── avater.jpg │ └── fonts │ │ ├── iconfont.eot │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.svg ├── components │ ├── BookDetail │ │ ├── Rate │ │ │ ├── star_on.png │ │ │ ├── star_half.png │ │ │ ├── star_off.png │ │ │ └── Rate.vue │ │ └── Like.vue │ ├── PullDown.vue │ ├── BackNav.vue │ ├── Reader │ │ ├── CatelogCover.vue │ │ ├── CatelogPanel.vue │ │ ├── ReaderFooter.vue │ │ └── FontPanel.vue │ ├── Home │ │ ├── Recommend.vue │ │ └── BookList.vue │ └── Loading.vue ├── stylus │ ├── base.styl │ ├── variable.styl │ ├── mixin.styl │ ├── reset.styl │ └── iconfont.styl ├── App.vue ├── store │ ├── local.js │ ├── index.js │ ├── types.js │ ├── actions.js │ └── mutations.js ├── main.js ├── router │ └── index.js └── pages │ ├── BookDetail.vue │ ├── Category.vue │ ├── Reader.vue │ └── Home.vue ├── .editorconfig ├── .gitignore ├── .postcssrc.js ├── index.html ├── .babelrc ├── README.md └── package.json /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/images/1.jpg -------------------------------------------------------------------------------- /src/assets/images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/images/2.jpg -------------------------------------------------------------------------------- /src/assets/images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/images/3.jpg -------------------------------------------------------------------------------- /src/assets/images/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/images/4.jpg -------------------------------------------------------------------------------- /src/assets/images/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/images/5.jpg -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/fonts/iconfont.eot -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/fonts/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/fonts/iconfont.woff -------------------------------------------------------------------------------- /src/assets/images/avater.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/assets/images/avater.jpg -------------------------------------------------------------------------------- /src/components/BookDetail/Rate/star_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/components/BookDetail/Rate/star_on.png -------------------------------------------------------------------------------- /src/components/BookDetail/Rate/star_half.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/components/BookDetail/Rate/star_half.png -------------------------------------------------------------------------------- /src/components/BookDetail/Rate/star_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangshouqi/vue-reader/HEAD/src/components/BookDetail/Rate/star_off.png -------------------------------------------------------------------------------- /src/stylus/base.styl: -------------------------------------------------------------------------------- 1 | html 2 | width: 100% 3 | min-height: 600px 4 | overflow-x: hidden 5 | font-size: 14px 6 | body 7 | text-algin: center 8 | width: 100% 9 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Editor directories and files 9 | .idea 10 | *.suo 11 | *.ntvs* 12 | *.njsproj 13 | *.sln 14 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserslist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/store/local.js: -------------------------------------------------------------------------------- 1 | const STORAGE_KEY = 'vue_reader_' // 为了避免重名,这里添加一个前缀 2 | 3 | export default { 4 | fetch(key) { 5 | return JSON.parse(window.localStorage.getItem(STORAGE_KEY + key) || '[]') 6 | }, 7 | save(key, val) { 8 | window.localStorage.setItem(STORAGE_KEY + key, JSON.stringify(val)) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vue-reader 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/stylus/variable.styl: -------------------------------------------------------------------------------- 1 | $color-home-theme = #f5f5f5 2 | $color-home-item = #fff 3 | 4 | $color-reader-bg-1 = #e9dfc7 // 杏仁黄 5 | $color-reader-bg-2 = #EAEAEF // 极光灰 6 | $color-reader-bg-3 = #FDE6E0 // 胭脂红 7 | $color-reader-bg-4 = #E3EDCD // 青草绿 8 | $color-reader-bg-5 = #DCE2F1 // 海天蓝 9 | $color-reader-bg-6 = #FFF2E2 // 秋叶褐 10 | 11 | $color-reader-bg-night = #0f1410 12 | -------------------------------------------------------------------------------- /src/stylus/mixin.styl: -------------------------------------------------------------------------------- 1 | no-wrap() 2 | overflow: hidden; 3 | text-overflow: ellipsis; 4 | white-space: nowrap; 5 | 6 | title-style() 7 | border-left: 2px solid red 8 | margin: 10px 5px 15px 9 | padding: 2px 12px 10 | font-size: 22px 11 | color: rgba(0, 0, 0, .7) 12 | 13 | booklist-item() 14 | padding: 5px 15 | margin-bottom: 15px 16 | background-color: #fff 17 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-runtime"], 12 | "env": { 13 | "test": { 14 | "presets": ["env", "stage-2"], 15 | "plugins": ["istanbul"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/components/PullDown.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | 22 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import actions from './actions' 4 | import mutations from './mutations' 5 | 6 | Vue.use(Vuex) 7 | 8 | const state = { 9 | showNav: true, 10 | catelog_panel: false, 11 | font_panel: false, 12 | font_size: 16, 13 | curChapter: 1, 14 | bg_color: 1, 15 | bg_night: false, 16 | loading: true 17 | 18 | } 19 | 20 | export default new Vuex.Store({ 21 | state, 22 | mutations, 23 | actions, 24 | }) 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/components/BackNav.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 19 | 20 | 29 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import router from './router' 6 | import store from './store/index' 7 | 8 | import MintUI from 'mint-ui' 9 | import 'mint-ui/lib/style.css' 10 | 11 | Vue.use(MintUI) 12 | 13 | import axios from 'axios' 14 | 15 | Vue.prototype.$http = axios 16 | 17 | Vue.config.productionTip = false 18 | 19 | /* eslint-disable no-new */ 20 | new Vue({ 21 | el: '#app', 22 | router, 23 | store, 24 | template: '', 25 | components: {App} 26 | }) 27 | -------------------------------------------------------------------------------- /src/store/types.js: -------------------------------------------------------------------------------- 1 | // 切换上下导航栏显示 2 | export const TOGGLE_NAV = 'TOGGLE_NAV'; 3 | // 切换目录面板显示 4 | export const SHOW_CATELOG_PANEL = 'SHOW_CATELOG _PANEL' 5 | // 切换字体面板显示 6 | export const SHOW_FONT_PANEL = 'SHOW_FONT_PANEL' 7 | // 字体增大 8 | export const FONT_SIZE_ADD = 'FONT_SIZE_ADD' 9 | // 字体减小 10 | export const FONT_SIZE_DECREASE = 'FONT_SIZE_DECREASE' 11 | // 是否显示夜间模式 12 | export const SHOW_NIGHT = 'SHOW_NIGHT' 13 | // 上一章 14 | export const PREV_CHAPTER = 'PREV_CHAPTER' 15 | // 下一章 16 | export const NEXT_CHAPTER = 'NEXT_CHAPTER' 17 | // 当前章节 18 | export const CUR_CHAPTER = 'CUR_CHAPTER' 19 | // 切换loading 20 | export const TOGGLE_LOADING = 'TOGGLE_LOADING' 21 | -------------------------------------------------------------------------------- /src/components/Reader/CatelogCover.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 15 | 16 | 31 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Home from 'pages/Home' 4 | import Category from 'pages/Category' 5 | import BookDetail from 'pages/BookDetail' 6 | import Reader from 'pages/Reader' 7 | 8 | Vue.use(Router) 9 | 10 | export default new Router({ 11 | // mode: 'history', 12 | routes: [ 13 | { 14 | path: '/', 15 | redirect: '/home' 16 | }, 17 | { 18 | path: '/home', 19 | component: Home 20 | }, 21 | { 22 | path: '/category', 23 | component: Category 24 | }, 25 | { 26 | path: '/bookdetail/:id', 27 | component: BookDetail 28 | }, 29 | { 30 | path: '/reader/:id', 31 | component: Reader 32 | } 33 | ] 34 | }) 35 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './types' 2 | 3 | export default { 4 | toggleNav: ({commit}) => { 5 | commit(types.TOGGLE_NAV) 6 | }, 7 | showCatelogPanel({commit}) { 8 | commit(types.SHOW_CATELOG_PANEL) 9 | }, 10 | showFontPanel({commit}) { 11 | commit(types.SHOW_FONT_PANEL) 12 | }, 13 | fontSizeAdd({commit}) { 14 | commit(types.FONT_SIZE_ADD) 15 | }, 16 | fontSizeDecrease({commit}) { 17 | commit(types.FONT_SIZE_DECREASE) 18 | }, 19 | showNight({commit}) { 20 | commit(types.SHOW_NIGHT) 21 | }, 22 | prevChapter({commit}) { 23 | commit(types.PREV_CHAPTER) 24 | }, 25 | nextChapter({commit, maxChapter}) { 26 | commit(types.NEXT_CHAPTER, maxChapter) 27 | }, 28 | curChapter({commit}, num) { 29 | commit(types.CUR_CHAPTER, num) 30 | }, 31 | toggleLoading({commit}) { 32 | commit(types.TOGGLE_LOADING) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | import * as types from './types' 2 | 3 | export default { 4 | [types.TOGGLE_NAV](state) { 5 | state.showNav = !state.showNav 6 | }, 7 | [types.SHOW_CATELOG_PANEL](state) { 8 | state.catelog_panel = !state.catelog_panel 9 | }, 10 | [types.SHOW_FONT_PANEL](state) { 11 | state.font_panel = !state.font_panel 12 | }, 13 | [types.FONT_SIZE_ADD](state) { 14 | state.font_size++ 15 | if (state.font_size >= 24) { 16 | state.font_size = 24 17 | } 18 | }, 19 | [types.FONT_SIZE_DECREASE](state) { 20 | state.font_size-- 21 | if (state.font_size <= 14) { 22 | state.font_size = 14 23 | } 24 | }, 25 | [types.SHOW_NIGHT](state) { 26 | state.bg_night = !state.bg_night 27 | }, 28 | [types.PREV_CHAPTER](state) { 29 | if (state.curChapter <= 1) { 30 | return false 31 | } 32 | state.curChapter-- 33 | }, 34 | [types.NEXT_CHAPTER](state, maxChapter) { 35 | if (state.curChapter >= maxChapter) { 36 | return false 37 | } 38 | state.curChapter++ 39 | }, 40 | [types.CUR_CHAPTER](state, num) { 41 | state.curChapter = num 42 | }, 43 | [types.TOGGLE_LOADING](state) { 44 | state.loading = false 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/components/BookDetail/Like.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 41 | 42 | 53 | 54 | -------------------------------------------------------------------------------- /src/components/BookDetail/Rate/Rate.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 34 | 35 | 53 | -------------------------------------------------------------------------------- /src/components/Home/Recommend.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 25 | 26 | 56 | -------------------------------------------------------------------------------- /src/stylus/reset.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) 3 | * http://cssreset.com 4 | */ 5 | html, body, div, span, applet, object, iframe, 6 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 7 | a, abbr, acronym, address, big, cite, code, 8 | del, dfn, em, img, ins, kbd, q, s, samp, 9 | small, strike, strong, sub, sup, tt, var, 10 | b, u, i, center, 11 | dl, dt, dd, ol, ul, li, 12 | fieldset, form, label, legend, 13 | table, caption, tbody, tfoot, thead, tr, th, td, 14 | article, aside, canvas, details, embed, 15 | figure, figcaption, footer, header, 16 | menu, nav, output, ruby, section, summary, 17 | time, mark, audio, video, input 18 | margin: 0 19 | padding: 0 20 | border: 0 21 | font-size: 100% 22 | font-weight: normal 23 | vertical-align: baseline 24 | 25 | /* HTML5 display-role reset for older browsers */ 26 | article, aside, details, figcaption, figure, 27 | footer, header, menu, nav, section 28 | display: block 29 | 30 | body 31 | line-height: 1 32 | 33 | blockquote, q 34 | quotes: none 35 | 36 | blockquote:before, blockquote:after, 37 | q:before, q:after 38 | content: none 39 | 40 | table 41 | border-collapse: collapse 42 | border-spacing: 0 43 | 44 | /* custom */ 45 | 46 | a 47 | color: #7e8c8d 48 | -webkit-backface-visibility: hidden 49 | text-decoration: none 50 | 51 | li 52 | list-style: none 53 | 54 | body 55 | -webkit-text-size-adjust: none 56 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0) 57 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: './', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8080, 27 | autoOpenBrowser: true, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/components/Loading.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 | 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-reader 2 | 初学vue2.0,花几天时间模仿了一个小说阅读的WebApp,样式比较粗糙,参考了 [慕课网课程](http://coding.imooc.com/class/13.html) 和 [tgxhx](https://github.com/tgxhx/vue-reader/) 的项目,在其基础上进行了学习和改造。自我感觉代码还是有点混乱,仅仅实现了基本的功能,后期有时间的话会进行重构。 3 | 4 | > [在线预览](http://iwen.tianyan.hk) 5 | (手机预览和Chrome下f12效果最佳) 6 | 7 | >[源码地址](https://github.com/huangshouqi/vue-reader) 8 | 9 | > [api地址](https://github.com/tgxhx/node-book-api) 10 | 11 | ## 二维码扫描 12 | ![](http://ovh9m465i.bkt.clouddn.com/QRcode.png) 13 | 14 | 15 | ## 使用说明 16 | 17 | ``` bash 18 | # 克隆项目 19 | git clone git@github.com:huangshouqi/vue-reader.git 20 | # 安装依赖 21 | npm install 22 | # 本地开发环境 访问http://localhost:8080 23 | npm run dev 24 | # 构建生产 25 | npm run build 26 | ``` 27 | 28 | 29 | ## 技术栈 30 | - vue2.0+vue-router+vuex(vue全家桶) 31 | - mint-ui(使用了swipe和pull-down组件) 32 | - es6(javascript核心规范) 33 | - stylus (css预处理器) 34 | - axios(数据请求) 35 | - localStorage (HTML5本地存储) 36 | 37 | ## 功能 38 | - [x] 首页推荐 39 | - [x] 分类查看 40 | - [x] 书籍详情 41 | - [x] 相似推荐 42 | - [x] 目录跳转 43 | - [x] 下拉刷新 44 | - [x] 加载动画 45 | - [x] 更改字体 46 | - [x] 更换主题 47 | - [x] 夜间模式 48 | - [x] 记忆个性化设置 49 | ## 待加入功能 50 | - [ ] 书架 51 | - [ ] 搜索 52 | - [ ] 滑动翻页 53 | 54 | ## 预览图 55 | ### 首页 56 | ![](http://ovh9m465i.bkt.clouddn.com/1.png?imageMogr2/auto-orient/thumbnail/414x736!/blur/1x0/quality/75|imageslim) 57 | 58 | ### 分类页 59 | ![](http://ovh9m465i.bkt.clouddn.com/2.png?imageMogr2/auto-orient/thumbnail/414x736!/blur/1x0/quality/75|imageslim) 60 | 61 | ### 书籍详情页 62 | ![](http://ovh9m465i.bkt.clouddn.com/3.png?imageMogr2/auto-orient/thumbnail/414x736!/blur/1x0/quality/75|imageslim) 63 | 64 | ### 目录 65 | ![](http://ovh9m465i.bkt.clouddn.com/4.png?imageMogr2/auto-orient/thumbnail/414x736!/blur/1x0/quality/75|imageslim) 66 | 67 | ### 阅读器 68 | ![](http://ovh9m465i.bkt.clouddn.com/5.png?imageMogr2/auto-orient/thumbnail/414x736!/blur/1x0/quality/75|imageslim) 69 | 70 | ## More 71 | 欢迎大家提出不足与建议,我会进行改正 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-reader", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "Archie <614203973@qq.com>", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "start": "node build/dev-server.js", 10 | "build": "node build/build.js" 11 | }, 12 | "dependencies": { 13 | "axios": "^0.16.2", 14 | "mint-ui": "^2.2.9", 15 | "vue": "^2.4.2", 16 | "vue-router": "^2.7.0", 17 | "vuex": "^2.4.0" 18 | }, 19 | "devDependencies": { 20 | "autoprefixer": "^7.1.2", 21 | "babel-core": "^6.22.1", 22 | "babel-loader": "^7.1.1", 23 | "babel-plugin-transform-runtime": "^6.22.0", 24 | "babel-preset-env": "^1.3.2", 25 | "babel-preset-stage-2": "^6.22.0", 26 | "babel-register": "^6.22.0", 27 | "chalk": "^2.0.1", 28 | "connect-history-api-fallback": "^1.3.0", 29 | "copy-webpack-plugin": "^4.0.1", 30 | "css-loader": "^0.28.7", 31 | "cssnano": "^3.10.0", 32 | "eventsource-polyfill": "^0.9.6", 33 | "express": "^4.14.1", 34 | "extract-text-webpack-plugin": "^2.0.0", 35 | "file-loader": "^0.11.1", 36 | "friendly-errors-webpack-plugin": "^1.1.3", 37 | "html-webpack-plugin": "^2.28.0", 38 | "http-proxy-middleware": "^0.17.3", 39 | "opn": "^5.1.0", 40 | "optimize-css-assets-webpack-plugin": "^2.0.0", 41 | "ora": "^1.2.0", 42 | "rimraf": "^2.6.0", 43 | "semver": "^5.3.0", 44 | "shelljs": "^0.7.6", 45 | "style-loader": "^0.18.2", 46 | "stylus": "^0.54.5", 47 | "stylus-loader": "^3.0.1", 48 | "url-loader": "^0.5.8", 49 | "vue-loader": "^13.0.4", 50 | "vue-style-loader": "^3.0.1", 51 | "vue-template-compiler": "^2.4.2", 52 | "webpack": "^2.6.1", 53 | "webpack-bundle-analyzer": "^2.2.1", 54 | "webpack-dev-middleware": "^1.10.0", 55 | "webpack-hot-middleware": "^2.18.0", 56 | "webpack-merge": "^4.1.0" 57 | }, 58 | "engines": { 59 | "node": ">= 4.0.0", 60 | "npm": ">= 3.0.0" 61 | }, 62 | "browserslist": [ 63 | "> 1%", 64 | "last 2 versions", 65 | "not ie <= 8" 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /src/components/Reader/CatelogPanel.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 58 | 59 | 115 | -------------------------------------------------------------------------------- /src/components/Reader/ReaderFooter.vue: -------------------------------------------------------------------------------- 1 | 18 | 43 | 44 | 116 | -------------------------------------------------------------------------------- /src/components/Reader/FontPanel.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 56 | 57 | 120 | -------------------------------------------------------------------------------- /src/components/Home/BookList.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 45 | 46 | 120 | -------------------------------------------------------------------------------- /src/pages/BookDetail.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 89 | 90 | 146 | -------------------------------------------------------------------------------- /src/pages/Category.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 98 | 99 | 100 | 174 | -------------------------------------------------------------------------------- /src/stylus/iconfont.styl: -------------------------------------------------------------------------------- 1 | 2 | @font-face {font-family: "iconfont"; 3 | src: url('~assets/fonts/iconfont.eot?t=1504016729500'); /* IE9*/ 4 | src: url('~assets/fonts/iconfont.eot?t=1504016729500#iefix') format('embedded-opentype'), /* IE6-IE8 */ 5 | url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'), 6 | url('~assets/fonts/iconfont.ttf?t=1504016729500') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ 7 | url('~assets/fonts/iconfont.svg?t=1504016729500#iconfont') format('svg'); /* iOS 4.1- */ 8 | } 9 | 10 | .iconfont 11 | font-family:"iconfont" !important 12 | font-size:16px 13 | font-style:normal 14 | -webkit-font-smoothing: antialiased 15 | -moz-osx-font-smoothing: grayscale 16 | 17 | .icon-caidan:before { content: "\e641"; } 18 | 19 | .icon-iconfontfanhuidingbu:before { content: "\e631"; } 20 | 21 | .icon-lanmuzuozhe:before { content: "\e614"; } 22 | 23 | .icon-mianbanbaitian:before { content: "\e6eb"; } 24 | 25 | .icon-icon-yxj-font:before { content: "\e629"; } 26 | 27 | .icon-wangyeyouxi:before { content: "\e632"; } 28 | 29 | .icon-fanhui:before { content: "\e600"; } 30 | 31 | .icon-vuejs:before { content: "\e617"; } 32 | 33 | .icon-dushu:before { content: "\e622"; } 34 | 35 | .icon-xianxiaqiyuancopy:before { content: "\e601"; } 36 | 37 | .icon-xuanhuanyanqingcopy:before { content: "\e602"; } 38 | 39 | .icon-lishi1:before { content: "\e603"; } 40 | 41 | .icon-yejianmoshi-dianjiguozhuangtai:before { content: "\e621"; } 42 | 43 | -------------------------------------------------------------------------------- /src/pages/Reader.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 167 | 168 | 169 | 243 | -------------------------------------------------------------------------------- /src/pages/Home.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 199 | 200 | 201 | 266 | -------------------------------------------------------------------------------- /src/assets/fonts/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by iconfont 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | --------------------------------------------------------------------------------