├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .postcssrc.js ├── README.md ├── build ├── build.js ├── check-versions.js ├── dev-server.js ├── utils.js ├── vue-loader.conf.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js └── prod.env.js ├── package.json ├── project.config.json ├── src ├── App.vue ├── components │ ├── TopSwiper.vue │ ├── card.vue │ └── postsList.vue ├── main.js ├── packageA │ └── logs.vue ├── pages │ ├── about.vue │ ├── categories.vue │ ├── categoriesList.vue │ ├── counter.vue │ ├── home.vue │ ├── homeDetails.vue │ ├── index.vue │ └── webpage.vue ├── router │ └── router.js ├── store │ └── index.js └── utils │ ├── api.js │ ├── constant.js │ ├── enum.js │ ├── index.js │ ├── request.js │ └── wechat.js └── static ├── .gitkeep └── img ├── appreciation.png ├── calendar.png ├── category.png ├── comments.png ├── copy.png ├── forwarding.png ├── home-like.png ├── homepage.png ├── homepage_fill.png ├── like.png ├── manage.png ├── manage_fill.png ├── pageviews.png ├── poster.png ├── prompt.png └── prompt_fill.png /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: false, 11 | node: true, 12 | es6: true 13 | }, 14 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md 15 | extends: 'standard', 16 | // required to lint *.vue files 17 | plugins: [ 18 | 'html' 19 | ], 20 | // add your custom rules here 21 | 'rules': { 22 | // allow paren-less arrow functions 23 | 'arrow-parens': 0, 24 | // allow async-await 25 | 'generator-star-spacing': 0, 26 | // allow debugger during development 27 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 28 | }, 29 | globals: { 30 | App: true, 31 | Page: true, 32 | wx: true, 33 | getApp: true, 34 | getPage: true, 35 | requirePlugin: true 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=Vue 2 | *.css linguist-language=Vue 3 | *.html linguist-language=Vue -------------------------------------------------------------------------------- /.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 | "postcss-mpvue-wxss": {} 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blog-mpvue 2 | 3 | > 基于mpvue开发wordpress版微信小程序,帮助WordPress的网站用户,通过简单的配置,快速搭建微信小程序。配置文件路径:utils/constant.js 4 | 5 | ## 体验 6 | ![林朝昆Blog](https://blog.linchaokun.cn/wp-content/uploads/2018/08/qrcode.jpeg) 7 | 8 | ### 目录 9 | 10 | - [工具](#工具) 11 | - [框架](#框架) 12 | - [组件](#组件) 13 | - [模板](#模板) 14 | - [技术支持](#技术支持) 15 | 16 | ## 工具 17 | * [flyio](https://github.com/wendux/fly/blob/master/README-CH.md) - 同时支持浏览器、小程序、Node、Weex的基于Promise的跨平台http请求库。可以让您在多个端上尽可能大限度的实现代码复用。 18 | * [mpvue-entry](https://github.com/F-loat/mpvue-entry) - 集中式页面配置,避免重复编辑各页面的 main.js 文件,优化目录结构。 19 | * [mpvue-router-patch](https://github.com/F-loat/mpvue-router-patch) - 在 mpvue 中使用 vue-router 兼容的路由写法。 20 | 21 | ## 框架 22 | 23 | * [vant-weapp](https://github.com/youzan/vant-weapp) - 轻量、可靠的小程序 UI 组件库。 24 | * [iView Weapp](https://github.com/TalkingData/iview-weapp) - 一套高质量的微信小程序 UI 组件库。 25 | 26 | ## 组件 27 | 28 | * [mpvue-wxParse](https://github.com/F-loat/mpvue-wxParse) - 富文本组件,支持 Html、Markdown 转 Wxml 可视化 29 | 30 | 31 | ## 模板 32 | 33 | * [mpvue/mpvue-quickstart](https://github.com/mpvue/mpvue-quickstart) - quickstart 34 | * [F-loat/mpvue-quickstart](https://github.com/F-loat/mpvue-quickstart) - 使用 mpvue-entry 配置入口,支持新增页面热更新 35 | 36 | ## 技术支持 37 | * QQ:812086325 38 | * Q群:152643026 39 | * 邮箱:admin@linchaokun.cn 40 | * 网站:https://blog.linchaokun.cn 41 | 42 | 如你有好的想法或建议欢迎与我联系。 -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | const ora = require('ora') 6 | const rm = require('rimraf') 7 | const path = require('path') 8 | const chalk = require('chalk') 9 | const webpack = require('webpack') 10 | const config = require('../config') 11 | const webpackConfig = require('./webpack.prod.conf') 12 | 13 | const spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, '*'), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | if (stats.hasErrors()) { 30 | console.log(chalk.red(' Build failed with errors.\n')) 31 | process.exit(1) 32 | } 33 | 34 | console.log(chalk.cyan(' Build complete.\n')) 35 | console.log(chalk.yellow( 36 | ' Tip: built files are meant to be served over an HTTP server.\n' + 37 | ' Opening index.html over file:// won\'t work.\n' 38 | )) 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /build/check-versions.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk') 2 | const semver = require('semver') 3 | const shell = require('shelljs') 4 | const packageConfig = require('../package.json') 5 | 6 | function exec (cmd) { 7 | return require('child_process').execSync(cmd).toString().trim() 8 | } 9 | 10 | const versionRequirements = [ 11 | { 12 | name: 'node', 13 | currentVersion: semver.clean(process.version), 14 | versionRequirement: packageConfig.engines.node 15 | } 16 | ] 17 | 18 | if (shell.which('npm')) { 19 | versionRequirements.push({ 20 | name: 'npm', 21 | currentVersion: exec('npm --version'), 22 | versionRequirement: packageConfig.engines.npm 23 | }) 24 | } 25 | 26 | module.exports = function () { 27 | const warnings = [] 28 | for (let i = 0; i < versionRequirements.length; i++) { 29 | const mod = versionRequirements[i] 30 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 31 | warnings.push(mod.name + ': ' + 32 | chalk.red(mod.currentVersion) + ' should be ' + 33 | chalk.green(mod.versionRequirement) 34 | ) 35 | } 36 | } 37 | 38 | if (warnings.length) { 39 | console.log('') 40 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 41 | console.log() 42 | for (let i = 0; i < warnings.length; i++) { 43 | const warning = warnings[i] 44 | console.log(' ' + warning) 45 | } 46 | console.log() 47 | process.exit(1) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | const webpack = require('webpack') 4 | const hardDisk = require('webpack-dev-middleware-hard-disk') 5 | const config = require('../config') 6 | 7 | if (!process.env.NODE_ENV) { 8 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 9 | } 10 | 11 | const webpackConfig = process.env.NODE_ENV === 'production' 12 | ? require('./webpack.prod.conf') 13 | : require('./webpack.dev.conf') 14 | 15 | const compiler = webpack(webpackConfig) 16 | 17 | module.exports = hardDisk(compiler, { 18 | publicPath: webpackConfig.output.publicPath, 19 | quiet: true 20 | }) 21 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 3 | const config = require('../config') 4 | 5 | exports.assetsPath = function (_path) { 6 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | const cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | const postcssLoader = { 24 | loader: 'postcss-loader', 25 | options: { 26 | sourceMap: true 27 | } 28 | } 29 | 30 | const px2rpxLoader = { 31 | loader: 'px2rpx-loader', 32 | options: { 33 | baseDpr: 1, 34 | rpxUnit: 0.5 35 | } 36 | } 37 | 38 | // generate loader string to be used with extract text plugin 39 | function generateLoaders (loader, loaderOptions) { 40 | const loaders = [cssLoader, px2rpxLoader, postcssLoader] 41 | if (loader) { 42 | loaders.push({ 43 | loader: loader + '-loader', 44 | options: Object.assign({}, loaderOptions, { 45 | sourceMap: options.sourceMap 46 | }) 47 | }) 48 | } 49 | 50 | // Extract CSS when that option is specified 51 | // (which is the case during production build) 52 | if (options.extract) { 53 | return ExtractTextPlugin.extract({ 54 | use: loaders, 55 | fallback: 'vue-style-loader' 56 | }) 57 | } else { 58 | return ['vue-style-loader'].concat(loaders) 59 | } 60 | } 61 | 62 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 63 | return { 64 | css: generateLoaders(), 65 | wxss: generateLoaders(), 66 | postcss: generateLoaders(), 67 | less: generateLoaders('less'), 68 | sass: generateLoaders('sass', { indentedSyntax: true }), 69 | scss: generateLoaders('sass'), 70 | stylus: generateLoaders('stylus'), 71 | styl: generateLoaders('stylus') 72 | } 73 | } 74 | 75 | // Generate loaders for standalone style files (outside of .vue) 76 | exports.styleLoaders = function (options) { 77 | const output = [] 78 | const loaders = exports.cssLoaders(options) 79 | for (const extension in loaders) { 80 | const loader = loaders[extension] 81 | output.push({ 82 | test: new RegExp('\\.' + extension + '$'), 83 | use: loader 84 | }) 85 | } 86 | return output 87 | } 88 | -------------------------------------------------------------------------------- /build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | const utils = require('./utils') 2 | const config = require('../config') 3 | 4 | module.exports = { 5 | loaders: utils.cssLoaders({ 6 | sourceMap: config.build.productionSourceMap, 7 | extract: true 8 | }), 9 | transformToRequire: { 10 | video: 'src', 11 | source: 'src', 12 | img: 'src', 13 | image: 'xlink:href' 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const MpvuePlugin = require('webpack-mpvue-asset-plugin') 4 | const MpvueEntry = require('mpvue-entry') 5 | const utils = require('./utils') 6 | const config = require('../config') 7 | const vueLoaderConfig = require('./vue-loader.conf') 8 | 9 | function resolve (dir) { 10 | return path.join(__dirname, '..', dir) 11 | } 12 | 13 | module.exports = { 14 | // 通过 src/pages.js 来配置要打包的页面, 15 | entry: MpvueEntry.getEntry('src/router/router.js'), 16 | target: require('mpvue-webpack-target'), 17 | output: { 18 | path: config.build.assetsRoot, 19 | filename: utils.assetsPath('../[name]/js/main.js'), 20 | chunkFilename: utils.assetsPath('../[id]/js/main.js'), 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue': 'mpvue', 29 | '@': resolve('src') 30 | }, 31 | symlinks: false, 32 | aliasFields: ['mpvue', 'weapp', 'browser'], 33 | mainFields: ['browser', 'module', 'main'] 34 | }, 35 | module: { 36 | rules: [ 37 | // { 38 | // test: /\.(js|vue)$/, 39 | // loader: 'eslint-loader', 40 | // enforce: 'pre', 41 | // include: resolve('src'), 42 | // options: { 43 | // formatter: require('eslint-friendly-formatter') 44 | // } 45 | // }, 46 | { 47 | test: /\.vue$/, 48 | loader: '@f-loat/mpvue-loader', 49 | options: vueLoaderConfig 50 | }, 51 | { 52 | test: /\.js$/, 53 | include: resolve('src'), 54 | use: [ 55 | 'babel-loader', 56 | { 57 | loader: '@f-loat/mpvue-loader', 58 | options: { 59 | checkMPEntry: true 60 | } 61 | }, 62 | ] 63 | }, 64 | { 65 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 66 | loader: 'url-loader', 67 | options: { 68 | name: utils.assetsPath('img/[name].[ext]') 69 | } 70 | }, 71 | { 72 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 73 | loader: 'url-loader', 74 | options: { 75 | limit: 10000, 76 | name: utils.assetsPath('media/[name].[ext]') 77 | } 78 | }, 79 | { 80 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 81 | loader: 'url-loader', 82 | options: { 83 | name: utils.assetsPath('fonts/[name].[ext]') 84 | } 85 | } 86 | ] 87 | }, 88 | plugins: [ 89 | new MpvuePlugin(), 90 | new MpvueEntry() 91 | ] 92 | } 93 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const merge = require('webpack-merge') 3 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 4 | const utils = require('./utils') 5 | const config = require('../config') 6 | const baseWebpackConfig = require('./webpack.base.conf') 7 | 8 | // copy from ./webpack.prod.conf.js 9 | const path = require('path') 10 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 11 | const CopyWebpackPlugin = require('copy-webpack-plugin') 12 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ 17 | sourceMap: config.dev.cssSourceMap, 18 | extract: true 19 | }) 20 | }, 21 | // cheap-module-eval-source-map is faster for development 22 | // devtool: '#cheap-module-eval-source-map', 23 | devtool: '#source-map', 24 | plugins: [ 25 | new webpack.DefinePlugin({ 26 | 'process.env': config.dev.env 27 | }), 28 | // copy from ./webpack.prod.conf.js 29 | // extract css into its own file 30 | new ExtractTextPlugin({ 31 | filename: utils.assetsPath('../[name]/css/main.wxss') 32 | }), 33 | // Compress extracted CSS. We are using this plugin so that possible 34 | // duplicated CSS from different components can be deduped. 35 | new OptimizeCSSPlugin({ 36 | cssProcessorOptions: { 37 | safe: true 38 | } 39 | }), 40 | new webpack.optimize.CommonsChunkPlugin({ 41 | name: 'vendor', 42 | minChunks: function (module, count) { 43 | // any required modules inside node_modules are extracted to vendor 44 | return ( 45 | module.resource && 46 | /\.js$/.test(module.resource) && 47 | module.resource.indexOf('node_modules') >= 0 48 | ) || count > 1 49 | } 50 | }), 51 | new webpack.optimize.CommonsChunkPlugin({ 52 | name: 'manifest', 53 | chunks: ['vendor'] 54 | }), 55 | // copy custom static assets 56 | new CopyWebpackPlugin([ 57 | { 58 | from: path.resolve(__dirname, '../static'), 59 | to: config.build.assetsSubDirectory, 60 | ignore: ['.*'] 61 | } 62 | ]), 63 | new webpack.NoEmitOnErrorsPlugin(), 64 | new FriendlyErrorsPlugin() 65 | ] 66 | }) 67 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const merge = require('webpack-merge') 4 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 5 | const CopyWebpackPlugin = require('copy-webpack-plugin') 6 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 7 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 8 | const utils = require('./utils') 9 | const config = require('../config') 10 | const baseWebpackConfig = require('./webpack.base.conf') 11 | 12 | const env = config.build.env 13 | 14 | const webpackConfig = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ 17 | sourceMap: config.build.productionSourceMap, 18 | extract: true 19 | }) 20 | }, 21 | devtool: config.build.productionSourceMap ? '#source-map' : false, 22 | plugins: [ 23 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 24 | new webpack.DefinePlugin({ 25 | 'process.env': env 26 | }), 27 | new UglifyJsPlugin({ 28 | sourceMap: true 29 | }), 30 | // extract css into its own file 31 | new ExtractTextPlugin({ 32 | filename: utils.assetsPath('../[name]/css/main.wxss') 33 | }), 34 | // Compress extracted CSS. We are using this plugin so that possible 35 | // duplicated CSS from different components can be deduped. 36 | new OptimizeCSSPlugin({ 37 | cssProcessorOptions: { 38 | safe: true 39 | } 40 | }), 41 | // keep module.id stable when vender modules does not change 42 | new webpack.HashedModuleIdsPlugin(), 43 | // split vendor js into its own file 44 | new webpack.optimize.CommonsChunkPlugin({ 45 | name: 'vendor', 46 | minChunks: function (module, count) { 47 | // any required modules inside node_modules are extracted to vendor 48 | return ( 49 | module.resource && 50 | /\.js$/.test(module.resource) && 51 | module.resource.indexOf('node_modules') >= 0 52 | ) || count > 1 53 | } 54 | }), 55 | // extract webpack runtime and module manifest to its own file in order to 56 | // prevent vendor hash from being updated whenever app bundle is updated 57 | new webpack.optimize.CommonsChunkPlugin({ 58 | name: 'manifest', 59 | chunks: ['vendor'] 60 | }), 61 | // copy custom static assets 62 | new CopyWebpackPlugin([ 63 | { 64 | from: path.resolve(__dirname, '../static'), 65 | to: config.build.assetsSubDirectory, 66 | ignore: ['.*'] 67 | } 68 | ]) 69 | ] 70 | }) 71 | 72 | if (config.build.bundleAnalyzerReport) { 73 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 74 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 75 | } 76 | 77 | module.exports = webpackConfig 78 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | assetsRoot: path.resolve(__dirname, '../dist'), 8 | assetsSubDirectory: 'static', 9 | assetsPublicPath: '/', 10 | productionSourceMap: false, 11 | // Gzip off by default as many popular static hosts such as 12 | // Surge or Netlify already gzip all static assets for you. 13 | // Before setting to `true`, make sure to: 14 | // npm install --save-dev compression-webpack-plugin 15 | productionGzip: false, 16 | productionGzipExtensions: ['js', 'css'], 17 | // Run the build command with an extra argument to 18 | // View the bundle analyzer report after build finishes: 19 | // `npm run build --report` 20 | // Set to `true` or `false` to always turn it on or off 21 | bundleAnalyzerReport: process.env.npm_config_report 22 | }, 23 | dev: { 24 | env: require('./dev.env'), 25 | assetsSubDirectory: 'static', 26 | assetsPublicPath: '/', 27 | // CSS Sourcemaps off by default because relative paths are "buggy" 28 | // with this option, according to the CSS-Loader README 29 | // (https://github.com/webpack/css-loader#sourcemaps) 30 | // In our experience, they generally work as expected, 31 | // just be aware of this issue when enabling this option. 32 | cssSourceMap: false 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog-mpvue", 3 | "version": "1.0.0", 4 | "description": "A Mpvue project", 5 | "author": "linchaokun ", 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 | "lint": "eslint --ext .js,.vue src" 12 | }, 13 | "dependencies": { 14 | "flyio": "^0.6.0", 15 | "mpvue": "^1.0.0", 16 | "mpvue-router-patch": "^0.2.1", 17 | "mpvue-wxparse": "^0.6.5", 18 | "vuex": "^3.0.0", 19 | "wxa-plugin-canvas": "^1.1.1" 20 | }, 21 | "devDependencies": { 22 | "@f-loat/mpvue-loader": "^1.0.0", 23 | "babel-core": "^6.26.0", 24 | "babel-eslint": "^8.2.0", 25 | "babel-loader": "^7.1.0", 26 | "babel-plugin-transform-runtime": "^6.22.0", 27 | "babel-preset-env": "^1.7.0", 28 | "babel-preset-stage-2": "^6.22.0", 29 | "babel-register": "^6.22.0", 30 | "chalk": "^2.4.0", 31 | "copy-webpack-plugin": "^4.5.0", 32 | "css-loader": "^0.28.0", 33 | "cssnano": "^3.10.0", 34 | "eslint": "^4.19.0", 35 | "eslint-config-standard": "^11.0.0", 36 | "eslint-friendly-formatter": "^4.0.0", 37 | "eslint-loader": "^2.0.0", 38 | "eslint-plugin-html": "^4.0.0", 39 | "eslint-plugin-import": "^2.11.0", 40 | "eslint-plugin-node": "^6.0.0", 41 | "eslint-plugin-promise": "^3.4.0", 42 | "eslint-plugin-standard": "^3.0.0", 43 | "extract-text-webpack-plugin": "^3.0.0", 44 | "file-loader": "^1.1.0", 45 | "friendly-errors-webpack-plugin": "^1.7.0", 46 | "mpvue-entry": "^1.4.7", 47 | "mpvue-template-compiler": "^1.0.0", 48 | "mpvue-webpack-target": "^1.0.0", 49 | "node-sass": "^4.9.3", 50 | "optimize-css-assets-webpack-plugin": "^3.2.0", 51 | "ora": "^2.0.0", 52 | "postcss-loader": "^2.1.0", 53 | "postcss-mpvue-wxss": "^1.0.0", 54 | "prettier": "~1.12.0", 55 | "px2rpx-loader": "^0.1.0", 56 | "rimraf": "^2.6.0", 57 | "sass-loader": "^7.1.0", 58 | "semver": "^5.3.0", 59 | "shelljs": "^0.8.0", 60 | "uglifyjs-webpack-plugin": "^1.2.0", 61 | "url-loader": "^1.0.0", 62 | "vue-style-loader": "^4.1.0", 63 | "webpack": "3.11.0", 64 | "webpack-bundle-analyzer": "2.13.0", 65 | "webpack-dev-middleware-hard-disk": "1.12.0", 66 | "webpack-merge": "4.1.0", 67 | "webpack-mpvue-asset-plugin": "0.0.2" 68 | }, 69 | "engines": { 70 | "node": ">= 4.0.0", 71 | "npm": ">= 3.0.0" 72 | }, 73 | "browserslist": [ 74 | "> 1%", 75 | "last 2 versions", 76 | "not ie <= 8" 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件。", 3 | "setting": { 4 | "urlCheck": false, 5 | "es6": true, 6 | "postcss": true, 7 | "minified": true, 8 | "newFeature": true 9 | }, 10 | "miniprogramRoot": "./dist/", 11 | "compileType": "miniprogram", 12 | "appid": "wxcc78042cf8e43b04", 13 | "projectname": "blog-mpvue", 14 | "condition": { 15 | "search": { 16 | "current": -1, 17 | "list": [] 18 | }, 19 | "conversation": { 20 | "current": -1, 21 | "list": [] 22 | }, 23 | "game": { 24 | "currentL": -1, 25 | "list": [] 26 | }, 27 | "miniprogram": { 28 | "current": -1, 29 | "list": [] 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 36 | -------------------------------------------------------------------------------- /src/components/TopSwiper.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 42 | 51 | 52 | -------------------------------------------------------------------------------- /src/components/card.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /src/components/postsList.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 58 | 59 | 117 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from '@/App' 3 | import store from '@/store' 4 | import MpvueRouterPatch from 'mpvue-router-patch' 5 | 6 | Vue.use(MpvueRouterPatch) 7 | 8 | Vue.config.productionTip = false 9 | App.store = store 10 | App.mpType = 'app' 11 | 12 | const app = new Vue(App) 13 | app.$mount() 14 | 15 | export default { 16 | // 这个字段走 app.json 17 | config: { 18 | pages: [], 19 | window: { 20 | backgroundTextStyle: 'light', 21 | navigationBarBackgroundColor: '#39f', 22 | navigationBarTitleText: '林朝昆Blog', 23 | navigationBarTextStyle: 'while' 24 | }, 25 | tabBar: { 26 | color: '#fff', 27 | selectedColor: '#fff', 28 | backgroundColor: '#39f', 29 | list: [{ 30 | iconPath: './static/img/homepage.png', 31 | selectedIconPath: './static/img/homepage_fill.png', 32 | pagePath: 'pages/home', 33 | text: '首页' 34 | }, { 35 | iconPath: './static/img/manage.png', 36 | selectedIconPath: './static/img/manage_fill.png', 37 | pagePath: 'pages/categories', 38 | text: '分类' 39 | }, { 40 | iconPath: './static/img/prompt.png', 41 | selectedIconPath: './static/img/prompt_fill.png', 42 | pagePath: 'pages/about', 43 | text: '关于' 44 | }] 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/packageA/logs.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 32 | 33 | 44 | -------------------------------------------------------------------------------- /src/pages/about.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 47 | 48 | 80 | -------------------------------------------------------------------------------- /src/pages/categories.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 57 | 58 | 113 | -------------------------------------------------------------------------------- /src/pages/categoriesList.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 96 | 97 | 152 | -------------------------------------------------------------------------------- /src/pages/counter.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 30 | 31 | 44 | -------------------------------------------------------------------------------- /src/pages/home.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 120 | 121 | 126 | -------------------------------------------------------------------------------- /src/pages/homeDetails.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 138 | 147 | 148 | 149 | 236 | -------------------------------------------------------------------------------- /src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 71 | 72 | 109 | -------------------------------------------------------------------------------- /src/pages/webpage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 30 | 33 | 34 | -------------------------------------------------------------------------------- /src/router/router.js: -------------------------------------------------------------------------------- 1 | // 首个路由为首页 2 | module.exports = [ 3 | 4 | { 5 | path: 'pages/home', 6 | name: 'home', 7 | config: { 8 | navigationBarTitleText: '首页', 9 | backgroundTextStyle: "light", 10 | backgroundColor: "#39f", 11 | enablePullDownRefresh: true, 12 | usingComponents: { 13 | "van-search": "../vant-ui/search/index", 14 | "i-divider": "../iview-ui/divider/index", 15 | "van-tag": "../vant-ui/tag/index" 16 | } 17 | } 18 | }, 19 | { 20 | path: 'pages/homeDetails', 21 | name: 'details', 22 | config: { 23 | navigationBarTitleText: '详情', 24 | usingComponents: { 25 | "i-divider": "../iview-ui/divider/index" 26 | } 27 | } 28 | }, 29 | { 30 | path: 'pages/webpage', 31 | name: 'webpage', 32 | }, 33 | { 34 | path: 'pages/categories', 35 | name: 'categories', 36 | config: { 37 | navigationBarTitleText: '分类', 38 | backgroundTextStyle: "light", 39 | backgroundColor: "#39f", 40 | enablePullDownRefresh: true, 41 | usingComponents: { 42 | "i-divider": "../iview-ui/divider/index" 43 | } 44 | } 45 | }, 46 | { 47 | path: 'pages/categoriesList', 48 | name: 'categoriesList', 49 | config: { 50 | navigationBarTitleText: '分类列表', 51 | usingComponents: { 52 | "i-divider": "../iview-ui/divider/index" 53 | } 54 | } 55 | }, 56 | { 57 | path: 'pages/about', 58 | name: 'about', 59 | config: { 60 | navigationBarTitleText: '关于', 61 | usingComponents: { 62 | "i-divider": "../iview-ui/divider/index" 63 | } 64 | } 65 | }, 66 | { 67 | path: 'pages/index', 68 | name: 'Index', 69 | config: { 70 | navigationBarTitleText: '文章详情', 71 | } 72 | }, 73 | { 74 | path: 'pages/counter', 75 | name: 'List', 76 | config: { 77 | navigationBarTitleText: 'list详情' 78 | } 79 | } 80 | ] -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | // https://vuex.vuejs.org/zh-cn/intro.html 2 | // make sure to call Vue.use(Vuex) if using a module system 3 | import Vue from 'vue' 4 | import Vuex from 'vuex' 5 | 6 | Vue.use(Vuex) 7 | 8 | const store = new Vuex.Store({ 9 | state: { 10 | count: 0 11 | }, 12 | mutations: { 13 | increment: (state) => { 14 | const obj = state 15 | obj.count += 1 16 | }, 17 | decrement: (state) => { 18 | const obj = state 19 | obj.count -= 1 20 | } 21 | } 22 | }) 23 | 24 | export default store 25 | -------------------------------------------------------------------------------- /src/utils/api.js: -------------------------------------------------------------------------------- 1 | //vue init F-loat/mpvue-quickstart my-project(初始化项目) 2 | import request from'./request' 3 | import enums from './enum' 4 | 5 | // 获取首页文章数据 6 | export const posts = (data) => request.get(enums.posts+data.page+"&search="+data.search+(data.categories==0?"":"&categories="+data.categories)) 7 | // 获取文章详情 8 | export const postsDetails = (data) => request.get(enums.postsDetails+data) 9 | // 获取分类 10 | export const categories = () => request.get(enums.categories) 11 | // 获取分类信息 12 | export const categorieInfo = (data) => request.get(enums.categorieInfo+data) 13 | // 获取页面 14 | export const pages = () => request.get(enums.pages) 15 | 16 | //注册 17 | // export const reqister= (data) => request.post(enums.register,data) 18 | -------------------------------------------------------------------------------- /src/utils/constant.js: -------------------------------------------------------------------------------- 1 | 2 | //地址 3 | export const baseUrl = "https://blog.linchaokun.cn" 4 | // 地址前缀 5 | export const leftUrl = "/wp-json/wp/v2" 6 | // 小程序名称 7 | export const appName = "林朝昆Blog" 8 | // 关于页面id 9 | export const aboutId = 50 10 | // 关于页面 头部图片 11 | export const aboutImg = "https://blog.linchaokun.cn/wp-content/uploads/2018/08/稿定设计导出-20180825-202545.png" 12 | // 关于页面 头部文字 13 | export const aboutText = "疯狂源自梦想,技术成就辉煌" 14 | // 第二行 15 | export const aboutText2 = "行走在人生路上,总会有许多得失和起落" 16 | // 赞赏图片 17 | export const zanshang = "https://blog.linchaokun.cn/wp-content/uploads/2018/08/微信收款.jpg" 18 | 19 | //首页轮播图 20 | export const tops = [ 21 | { 22 | src: 23 | "https://blog.linchaokun.cn/wp-content/uploads/2018/08/稿定设计导出-20180824-085943.png", 24 | title: "林朝昆Blog", 25 | url: "https://blog.linchaokun.cn" 26 | }, 27 | { 28 | src: 29 | "https://blog.linchaokun.cn/wp-content/uploads/2018/08/稿定设计导出-20180825-202545.png", 30 | title: "林朝昆Blog", 31 | url: "https://blog.linchaokun.cn" 32 | } 33 | ] 34 | 35 | // 底部版权信息 36 | export const copyInfo = "© 2018 林朝昆Blog blog.linchaokun.cn" 37 | -------------------------------------------------------------------------------- /src/utils/enum.js: -------------------------------------------------------------------------------- 1 | import { leftUrl,aboutId} from './constant' 2 | 3 | // 获取首页文章数据 4 | const posts = leftUrl+'/posts?per_page=10&orderby=date&order=desc&page=' 5 | // 获取文章详情 6 | const postsDetails = leftUrl+'/posts/' 7 | // 获取分类列表 8 | const categories = leftUrl+'/categories?per_page=10&orderby=count&order=desc' 9 | // 获取分类信息 10 | const categorieInfo = leftUrl+'/categories/' 11 | 12 | // 获取页面 13 | const pages = leftUrl+'/pages/'+aboutId 14 | 15 | export default { 16 | posts:posts, 17 | postsDetails:postsDetails, 18 | categories: categories, 19 | pages: pages, 20 | categorieInfo: categorieInfo 21 | } 22 | -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | function formatNumber (n) { 2 | const str = n.toString() 3 | return str[1] ? str : `0${str}` 4 | } 5 | 6 | export function formatTime (date) { 7 | const year = date.getFullYear() 8 | const month = date.getMonth() + 1 9 | const day = date.getDate() 10 | 11 | const hour = date.getHours() 12 | const minute = date.getMinutes() 13 | const second = date.getSeconds() 14 | 15 | const t1 = [year, month, day].map(formatNumber).join('/') 16 | const t2 = [hour, minute, second].map(formatNumber).join(':') 17 | 18 | return `${t1} ${t2}` 19 | } 20 | 21 | export default { 22 | formatNumber, 23 | formatTime 24 | } 25 | -------------------------------------------------------------------------------- /src/utils/request.js: -------------------------------------------------------------------------------- 1 | 2 | import { baseUrl} from './constant' 3 | var Fly=require("flyio/dist/npm/wx.js") //wx.js为flyio的微信小程序入口文件 4 | const request = new Fly() 5 | 6 | request.config.baseURL=baseUrl 7 | request.config.timeout=5000 8 | 9 | request.interceptors.request.use((request) => { 10 | // const csrfToken=wx.getStorageSync('authToken') 11 | 12 | // if(csrfToken){ 13 | // const csrfTokenFormat=csrfToken 14 | // request.headers['Authorization']=`Bearer ${csrfTokenFormat.accessToken}` 15 | // } 16 | 17 | wx.showLoading({title:'加载中...'}) 18 | return request 19 | }) 20 | 21 | request.interceptors.response.use( 22 | (response, promise) => { 23 | 24 | 25 | wx.hideLoading() 26 | return promise.resolve(response.data) 27 | }, 28 | (err, promise) => { 29 | wx.hideLoading() 30 | if(err){ 31 | switch(err.status){ 32 | case 400: 33 | wx.showToast({title:'没有更多数据'}) 34 | break; 35 | case 401 : 36 | wx.clearStorageSync() 37 | // wx.redirectTo({ 38 | // url:'/pages/login/login' 39 | // }) 40 | break; 41 | 42 | default: 43 | wx.showToast({title:'连接错误'}) 44 | } 45 | }else{ 46 | wx.showToast({ 47 | title:'请检查您的网络', 48 | icon:'none', 49 | duration:2000 50 | }) 51 | } 52 | return promise.resolve() 53 | } 54 | ) 55 | 56 | export default request -------------------------------------------------------------------------------- /src/utils/wechat.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | import enums from './enum' 4 | 5 | import { baseUrl } from './constant' 6 | 7 | export const setStorage= (key,val)=>{ 8 | return new Promise( (resolve,reject) =>{ 9 | wx.setStorage({ 10 | key:key, 11 | data:val, 12 | success:function(res){ 13 | resolve(res) 14 | }, 15 | fail:function(err){ 16 | reject(err) 17 | } 18 | }) 19 | }) 20 | } 21 | 22 | export const getStorage= (key) => { 23 | return new Promise((resolve,reject) => { 24 | wx.getStorage({ 25 | key:key, 26 | success:function(res){ 27 | resolve(res) 28 | }, 29 | fail:function(err){ 30 | reject(err) 31 | } 32 | }) 33 | }) 34 | } 35 | 36 | //上传本地文件图片到服务器 37 | export const uploadFile = (data) => { 38 | const csrfToken=wx.getStorageSync('authToken') 39 | return new Promise((resolve,reject) =>{ 40 | wx.uploadFile({ 41 | url:baseUrl + enums.uploadMileageImg, 42 | filePath:data, 43 | formData:{"Content-Type": "image/jpg"}, 44 | name: 'file', 45 | header: {'Authorization':`Bearer ${csrfToken.accessToken}`, 46 | "Content-Type": "multipart/form-data", //表单提交时伴随文件上传的场合 47 | }, 48 | success: function (res) { 49 | resolve(res) 50 | }, 51 | fail: function (e) { 52 | reject(e) 53 | } 54 | }) 55 | }) 56 | } -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/.gitkeep -------------------------------------------------------------------------------- /static/img/appreciation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/appreciation.png -------------------------------------------------------------------------------- /static/img/calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/calendar.png -------------------------------------------------------------------------------- /static/img/category.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/category.png -------------------------------------------------------------------------------- /static/img/comments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/comments.png -------------------------------------------------------------------------------- /static/img/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/copy.png -------------------------------------------------------------------------------- /static/img/forwarding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/forwarding.png -------------------------------------------------------------------------------- /static/img/home-like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/home-like.png -------------------------------------------------------------------------------- /static/img/homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/homepage.png -------------------------------------------------------------------------------- /static/img/homepage_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/homepage_fill.png -------------------------------------------------------------------------------- /static/img/like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/like.png -------------------------------------------------------------------------------- /static/img/manage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/manage.png -------------------------------------------------------------------------------- /static/img/manage_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/manage_fill.png -------------------------------------------------------------------------------- /static/img/pageviews.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/pageviews.png -------------------------------------------------------------------------------- /static/img/poster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/poster.png -------------------------------------------------------------------------------- /static/img/prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/prompt.png -------------------------------------------------------------------------------- /static/img/prompt_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hualuoyixiao/wechat-wordpress-blog-mpvue/9dea9df101e29d4d288b403722a58f599a0c950a/static/img/prompt_fill.png --------------------------------------------------------------------------------