├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── README.md
├── build
├── build.js
├── check-versions.js
├── logo.png
├── 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
└── test.env.js
├── index.html
├── package.json
├── server
├── api.js
├── db.js
└── index.js
├── src
├── assets
│ └── logo.png
├── components
│ ├── comment.vue
│ ├── commonFooter.vue
│ ├── commonHeader.vue
│ ├── commonLayout.vue
│ ├── list.vue
│ ├── list_article.vue
│ ├── list_content.vue
│ ├── list_home.vue
│ └── message.vue
├── main.js
├── pages
│ ├── about.vue
│ ├── admin
│ │ ├── articleEdit.vue
│ │ ├── articleList.vue
│ │ └── demoEdit.vue
│ ├── archives.vue
│ ├── categories.vue
│ ├── collections.vue
│ ├── demo.vue
│ ├── detail.vue
│ ├── home.vue
│ ├── signin.vue
│ └── visiter
│ │ └── index.vue
├── router
│ └── index.js
└── store
│ └── index.js
├── static
├── .gitkeep
├── css
│ ├── font
│ │ ├── demo.css
│ │ ├── demo_fontclass.html
│ │ ├── demo_symbol.html
│ │ ├── demo_unicode.html
│ │ ├── iconfont.css
│ │ ├── iconfont.eot
│ │ ├── iconfont.js
│ │ ├── iconfont.js.gz
│ │ ├── iconfont.svg
│ │ ├── iconfont.ttf
│ │ └── iconfont.woff
│ ├── normalize.css
│ └── public.css
├── img
│ ├── avatar.png
│ ├── bg.jpg
│ ├── bg_admin.jpg
│ ├── p1.png
│ └── tao.ico
├── js
│ ├── animation.js
│ ├── public.js
│ └── tween.js
└── upload
│ └── avatar
│ ├── 1536199860345.png
│ └── 1536199928211.png
└── test
├── e2e
├── custom-assertions
│ └── elementCount.js
├── nightwatch.conf.js
├── runner.js
└── specs
│ └── test.js
└── unit
├── .eslintrc
├── jest.conf.js
├── setup.js
└── specs
└── HelloWorld.spec.js
/.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-vue-jsx", "transform-runtime"],
12 | "env": {
13 | "test": {
14 | "presets": ["env", "stage-2"],
15 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
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/
2 | /config/
3 | /dist/
4 | /*.js
5 | /test/unit/coverage/
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://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: true,
11 | },
12 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md
13 | extends: 'standard',
14 | // required to lint *.vue files
15 | plugins: [
16 | 'html'
17 | ],
18 | // add your custom rules here
19 | rules: {
20 | // allow async-await
21 | 'generator-star-spacing': 'off',
22 | // allow debugger during development
23 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | /test/unit/coverage/
8 | /test/e2e/reports/
9 | selenium-debug.log
10 |
11 | # Editor directories and files
12 | .idea
13 | .vscode
14 | *.suo
15 | *.ntvs*
16 | *.njsproj
17 | *.sln
18 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # taoLand
2 | >博客:vue全家桶+node+mongodb
3 |
4 | ## 介绍
5 | + 实现了用户注册、登录、检测登录、博客管理(文章的修改和删除)、文章编辑(Markdown)、标签分类等功能。
6 | + 前端使用vue全家桶(cli,router,vuex,axios),框架用的elmentUI
7 | + 后端使用node,框架用的express,mongoose
8 | + 数据库采用mongodb
9 | + 响应式,移动端勉强能看...
10 | ## 线上预览
11 | [https://www.yangyuetao.cn/](https://www.yangyuetao.cn/)
12 |
13 | ## 食用
14 | + 下载到本地
15 | + `git clone https://github.com/bestRenekton/taoLand.git`
16 | + 安装
17 | + `npm i`
18 | + 或者使用淘宝的`cnpm i`
19 | + 安装mongodb
20 | + mongodb安装可以用官网的4.0版本,不过安的时候会卡很久
21 | + 也可以安3.4,参考[https://www.cnblogs.com/xuanmanstein/p/7991589.html](https://www.cnblogs.com/xuanmanstein/p/7991589.html)
22 | + 启动mongodb
23 | + 进入server启动node
24 | + 开第一个命令行
25 | + cd进入项目根目录的server文件夹
26 | + `node index`
27 | + 看到`Mongo connection successed`即node启动成功
28 | + 启动项目
29 | + 再开第二个命令行,cd进入项目根目录
30 | + `npm run dev`
31 | + 打开`http://127.0.0.1:8080`
32 |
33 | ## 部署docker
34 | + 参考 [taoland_docker分支](https://github.com/bestRenekton/taoLand/tree/taoland_docker)
35 |
36 | ## tips
37 | + mongoDB可视化工具,Robo3T客户端比较好用
38 | + 留言系统的数据库设计可能有问题,毕竟自己的后端项目写的不多,欢迎后端朋友指导...
39 |
40 | ## react重构版
41 | 2020年用TypeScript,React,Koa重构了前后端,支持SSR,PWA了,UI总的来说更简洁,暗黑了...
42 | 源代码:[https://github.com/bestRenekton/taoland-react](https://github.com/bestRenekton/taoland-react)
43 |
44 |
45 |
--------------------------------------------------------------------------------
/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/build/logo.png
--------------------------------------------------------------------------------
/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader',
51 | publicPath: '../../' //注意: 此处根据路径, 自动更改
52 | })
53 | } else {
54 | return ['vue-style-loader'].concat(loaders)
55 | }
56 | }
57 |
58 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
59 | return {
60 | css: generateLoaders(),
61 | postcss: generateLoaders(),
62 | less: generateLoaders('less'),
63 | sass: generateLoaders('sass', { indentedSyntax: true }),
64 | scss: generateLoaders('sass'),
65 | stylus: generateLoaders('stylus'),
66 | styl: generateLoaders('stylus')
67 | }
68 | }
69 |
70 | // Generate loaders for standalone style files (outside of .vue)
71 | exports.styleLoaders = function (options) {
72 | const output = []
73 | const loaders = exports.cssLoaders(options)
74 |
75 | for (const extension in loaders) {
76 | const loader = loaders[extension]
77 | output.push({
78 | test: new RegExp('\\.' + extension + '$'),
79 | use: loader
80 | })
81 | }
82 |
83 | return output
84 | }
85 |
86 | exports.createNotifierCallback = () => {
87 | const notifier = require('node-notifier')
88 |
89 | return (severity, errors) => {
90 | if (severity !== 'error') return
91 |
92 | const error = errors[0]
93 | const filename = error.file && error.file.split('!').pop()
94 |
95 | notifier.notify({
96 | title: packageConfig.name,
97 | message: severity + ': ' + error.name,
98 | subtitle: filename || '',
99 | icon: path.join(__dirname, 'logo.png')
100 | })
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 | const createLintingRule = () => ({
12 | test: /\.(js|vue)$/,
13 | loader: 'eslint-loader',
14 | enforce: 'pre',
15 | include: [resolve('src'), resolve('test')],
16 | options: {
17 | formatter: require('eslint-friendly-formatter'),
18 | emitWarning: !config.dev.showEslintErrorsInOverlay
19 | }
20 | })
21 |
22 | module.exports = {
23 | context: path.resolve(__dirname, '../'),
24 | entry: {
25 | app: './src/main.js'
26 | },
27 | output: {
28 | path: config.build.assetsRoot,
29 | filename: '[name].js',
30 | publicPath: process.env.NODE_ENV === 'production'
31 | ? config.build.assetsPublicPath
32 | : config.dev.assetsPublicPath
33 | },
34 | resolve: {
35 | extensions: ['.js', '.vue', '.json'],
36 | alias: {
37 | 'vue$': 'vue/dist/vue.esm.js',
38 | '@': resolve('src'),
39 | }
40 | },
41 | module: {
42 | rules: [
43 | // ...(config.dev.useEslint ? [createLintingRule()] : []),
44 | {
45 | test: /\.vue$/,
46 | loader: 'vue-loader',
47 | options: vueLoaderConfig
48 | },
49 | {
50 | test: /\.js$/,
51 | loader: 'babel-loader',
52 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
53 | },
54 | {
55 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
56 | loader: 'url-loader',
57 | options: {
58 | limit: 10000,
59 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
60 | }
61 | },
62 | {
63 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
64 | loader: 'url-loader',
65 | options: {
66 | limit: 10000,
67 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
68 | }
69 | },
70 | {
71 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
72 | loader: 'url-loader',
73 | options: {
74 | limit: 10000,
75 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
76 | }
77 | }
78 | ]
79 | },
80 | node: {
81 | // prevent webpack from injecting useless setImmediate polyfill because Vue
82 | // source contains it (although only uses it if it's native).
83 | setImmediate: false,
84 | // prevent webpack from injecting mocks to Node native modules
85 | // that does not make sense for the client
86 | dgram: 'empty',
87 | fs: 'empty',
88 | net: 'empty',
89 | tls: 'empty',
90 | child_process: 'empty'
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | /* 增加express 20171126 */
17 | // const express = require('express')
18 | // const app = express()
19 | // var appData = require('../goods.json')//加载本地数据文件
20 | // // var goods = appData.goods
21 | // var apiRoutes = express.Router()
22 | // app.use('/api', apiRoutes)
23 | /* 增加express end */
24 |
25 | const devWebpackConfig = merge(baseWebpackConfig, {
26 | module: {
27 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
28 | },
29 | // cheap-module-eval-source-map is faster for development
30 | devtool: config.dev.devtool,
31 |
32 | // these devServer options should be customized in /config/index.js
33 | devServer: {
34 | clientLogLevel: 'warning',
35 | historyApiFallback: {
36 | rewrites: [
37 | { from: /.*/, to: path.join(config.dev.assetsPublicPath, 'index.html') },
38 | ],
39 | },
40 | hot: true,
41 | contentBase: false, // since we use CopyWebpackPlugin.
42 | compress: true,
43 | host: HOST || config.dev.host,
44 | port: PORT || config.dev.port,
45 | open: config.dev.autoOpenBrowser,
46 | overlay: config.dev.errorOverlay
47 | ? { warnings: false, errors: true }
48 | : false,
49 | publicPath: config.dev.assetsPublicPath,
50 | proxy: config.dev.proxyTable,
51 | quiet: true, // necessary for FriendlyErrorsPlugin
52 | watchOptions: {
53 | poll: config.dev.poll,
54 | },
55 | /* 增加express 20171126 */
56 | // before(app) {
57 | // app.get('/api2/goods', (req, res) => {
58 | // res.json({
59 | // code: 0,
60 | // data: appData
61 | // })
62 | // })
63 | // }
64 | /* 增加路由规则 end */
65 | },
66 | plugins: [
67 | new webpack.DefinePlugin({
68 | 'process.env': require('../config/dev.env')
69 | }),
70 | new webpack.HotModuleReplacementPlugin(),
71 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
72 | new webpack.NoEmitOnErrorsPlugin(),
73 | // https://github.com/ampedandwired/html-webpack-plugin
74 | new HtmlWebpackPlugin({
75 | filename: 'index.html',
76 | template: 'index.html',
77 | inject: true
78 | }),
79 | // copy custom static assets
80 | new CopyWebpackPlugin([
81 | {
82 | from: path.resolve(__dirname, '../static'),
83 | to: config.dev.assetsSubDirectory,
84 | ignore: ['.*']
85 | }
86 | ])
87 | ]
88 | })
89 |
90 | module.exports = new Promise((resolve, reject) => {
91 | portfinder.basePort = process.env.PORT || config.dev.port
92 | portfinder.getPort((err, port) => {
93 | if (err) {
94 | reject(err)
95 | } else {
96 | // publish the new Port, necessary for e2e tests
97 | process.env.PORT = port
98 | // add port to devServer config
99 | devWebpackConfig.devServer.port = port
100 |
101 | // Add FriendlyErrorsPlugin
102 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
103 | compilationSuccessInfo: {
104 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
105 | },
106 | onErrors: config.dev.notifyOnErrors
107 | ? utils.createNotifierCallback()
108 | : undefined
109 | }))
110 |
111 | resolve(devWebpackConfig)
112 | }
113 | })
114 | })
115 |
--------------------------------------------------------------------------------
/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = process.env.NODE_ENV === 'testing'
15 | ? require('../config/test.env')
16 | : require('../config/prod.env')
17 |
18 | const webpackConfig = merge(baseWebpackConfig, {
19 | module: {
20 | rules: utils.styleLoaders({
21 | sourceMap: config.build.productionSourceMap,
22 | extract: true,
23 | usePostCSS: true
24 | })
25 | },
26 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
27 | output: {
28 | path: config.build.assetsRoot,
29 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
30 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
31 | },
32 | plugins: [
33 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
34 | new webpack.DefinePlugin({
35 | 'process.env': env
36 | }),
37 | new UglifyJsPlugin({
38 | uglifyOptions: {
39 | compress: {
40 | warnings: false
41 | }
42 | },
43 | sourceMap: config.build.productionSourceMap,
44 | parallel: true
45 | }),
46 | // extract css into its own file
47 | new ExtractTextPlugin({
48 | filename: utils.assetsPath('css/[name].[contenthash].css'),
49 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
50 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
51 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
52 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
53 | allChunks: true,
54 | }),
55 | // Compress extracted CSS. We are using this plugin so that possible
56 | // duplicated CSS from different components can be deduped.
57 | new OptimizeCSSPlugin({
58 | cssProcessorOptions: config.build.productionSourceMap
59 | ? { safe: true, map: { inline: false } }
60 | : { safe: true }
61 | }),
62 | // generate dist index.html with correct asset hash for caching.
63 | // you can customize output by editing /index.html
64 | // see https://github.com/ampedandwired/html-webpack-plugin
65 | new HtmlWebpackPlugin({
66 | filename: process.env.NODE_ENV === 'testing'
67 | ? 'index.html'
68 | : config.build.index,
69 | template: 'index.html',
70 | inject: true,
71 | minify: {
72 | removeComments: true,
73 | collapseWhitespace: true,
74 | removeAttributeQuotes: true
75 | // more options:
76 | // https://github.com/kangax/html-minifier#options-quick-reference
77 | },
78 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
79 | chunksSortMode: 'dependency'
80 | }),
81 | // keep module.id stable when vendor modules does not change
82 | new webpack.HashedModuleIdsPlugin(),
83 | // enable scope hoisting
84 | new webpack.optimize.ModuleConcatenationPlugin(),
85 | // split vendor js into its own file
86 | new webpack.optimize.CommonsChunkPlugin({
87 | name: 'vendor',
88 | minChunks (module) {
89 | // any required modules inside node_modules are extracted to vendor
90 | return (
91 | module.resource &&
92 | /\.js$/.test(module.resource) &&
93 | module.resource.indexOf(
94 | path.join(__dirname, '../node_modules')
95 | ) === 0
96 | )
97 | }
98 | }),
99 | // extract webpack runtime and module manifest to its own file in order to
100 | // prevent vendor hash from being updated whenever app bundle is updated
101 | new webpack.optimize.CommonsChunkPlugin({
102 | name: 'manifest',
103 | minChunks: Infinity
104 | }),
105 | // This instance extracts shared chunks from code splitted chunks and bundles them
106 | // in a separate chunk, similar to the vendor chunk
107 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
108 | new webpack.optimize.CommonsChunkPlugin({
109 | name: 'app',
110 | async: 'vendor-async',
111 | children: true,
112 | minChunks: 3
113 | }),
114 |
115 | // copy custom static assets
116 | new CopyWebpackPlugin([
117 | {
118 | from: path.resolve(__dirname, '../static'),
119 | to: config.build.assetsSubDirectory,
120 | ignore: ['.*']
121 | }
122 | ])
123 | ]
124 | })
125 |
126 | if (config.build.productionGzip) {
127 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
128 |
129 | webpackConfig.plugins.push(
130 | new CompressionWebpackPlugin({
131 | asset: '[path].gz[query]',
132 | algorithm: 'gzip',
133 | test: new RegExp(
134 | '\\.(' +
135 | config.build.productionGzipExtensions.join('|') +
136 | ')$'
137 | ),
138 | threshold: 10240,
139 | minRatio: 0.8
140 | })
141 | )
142 | }
143 |
144 | if (config.build.bundleAnalyzerReport) {
145 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
146 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
147 | }
148 |
149 | module.exports = webpackConfig
150 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.2.8
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {//代理
14 | '/api': {
15 | target: 'http://127.0.0.1:8088/api/',
16 | changeOrigin: true,
17 | pathRewrite: {
18 | '^/api': ''
19 | }
20 | }
21 | },
22 |
23 | // Various Dev Server settings
24 | host: '127.0.0.1', // can be overwritten by process.env.HOST
25 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
26 | autoOpenBrowser: false,
27 | errorOverlay: true,
28 | notifyOnErrors: true,
29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
30 |
31 | // Use Eslint Loader?
32 | // If true, your code will be linted during bundling and
33 | // linting errors and warnings will be shown in the console.
34 | useEslint: true,
35 | // If true, eslint errors and warnings will also be shown in the error overlay
36 | // in the browser.
37 | showEslintErrorsInOverlay: false,
38 |
39 | /**
40 | * Source Maps
41 | */
42 |
43 | // https://webpack.js.org/configuration/devtool/#development
44 | devtool: 'cheap-module-eval-source-map',
45 |
46 | // If you have problems debugging vue-files in devtools,
47 | // set this to false - it *may* help
48 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
49 | cacheBusting: true,
50 |
51 | cssSourceMap: true,
52 | },
53 |
54 | build: {
55 | // Template for index.html
56 | index: path.resolve(__dirname, '../dist/index.html'),
57 |
58 | // Paths
59 | assetsRoot: path.resolve(__dirname, '../dist'),
60 | assetsSubDirectory: 'static',
61 | assetsPublicPath: './',
62 |
63 | /**
64 | * Source Maps
65 | */
66 |
67 | productionSourceMap: true,
68 | // https://webpack.js.org/configuration/devtool/#production
69 | devtool: '#source-map',
70 |
71 | // Gzip off by default as many popular static hosts such as
72 | // Surge or Netlify already gzip all static assets for you.
73 | // Before setting to `true`, make sure to:
74 | // npm install --save-dev compression-webpack-plugin
75 | productionGzip: true,//开启gzip压缩
76 | productionGzipExtensions: ['js', 'css'],
77 |
78 | // Run the build command with an extra argument to
79 | // View the bundle analyzer report after build finishes:
80 | // `npm run build --report`
81 | // Set to `true` or `false` to always turn it on or off
82 | bundleAnalyzerReport: process.env.npm_config_report
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/config/test.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const devEnv = require('./dev.env')
4 |
5 | module.exports = merge(devEnv, {
6 | NODE_ENV: '"testing"'
7 | })
8 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | taoland
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "taoland",
3 | "version": "1.0.0",
4 | "description": "A Vue.js project",
5 | "author": "yangyuetao",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "unit": "jest --config test/unit/jest.conf.js --coverage",
11 | "e2e": "node test/e2e/runner.js",
12 | "test": "npm run unit && npm run e2e",
13 | "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs",
14 | "build": "node build/build.js"
15 | },
16 | "dependencies": {
17 | "async-validator": "^1.8.2",
18 | "axios": "^0.18.0",
19 | "cors": "^2.8.4",
20 | "deepmerge": "^2.0.1",
21 | "element-ui": "^2.0.10",
22 | "express": "^4.16.2",
23 | "express-session": "^1.15.6",
24 | "jsonwebtoken": "^8.2.0",
25 | "mavon-editor": "^2.4.16",
26 | "mongoose": "^5.0.6",
27 | "vue": "^2.5.2",
28 | "vue-hot-reload-api": "^2.2.4",
29 | "vue-resource": "^1.3.5",
30 | "vue-router": "^3.0.1",
31 | "vuex": "^3.0.1"
32 | },
33 | "devDependencies": {
34 | "autoprefixer": "^7.1.2",
35 | "babel-core": "^6.22.1",
36 | "babel-eslint": "^7.1.1",
37 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
38 | "babel-jest": "^21.0.2",
39 | "babel-loader": "^7.1.1",
40 | "babel-plugin-dynamic-import-node": "^1.2.0",
41 | "babel-plugin-syntax-jsx": "^6.18.0",
42 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
43 | "babel-plugin-transform-runtime": "^6.22.0",
44 | "babel-plugin-transform-vue-jsx": "^3.5.0",
45 | "babel-preset-env": "^1.3.2",
46 | "babel-preset-stage-2": "^6.22.0",
47 | "babel-register": "^6.22.0",
48 | "body-parser": "^1.18.2",
49 | "chalk": "^2.0.1",
50 | "chromedriver": "^2.27.2",
51 | "compression-webpack-plugin": "^1.1.11",
52 | "copy-webpack-plugin": "^4.0.1",
53 | "cross-spawn": "^5.0.1",
54 | "css-loader": "^0.28.8",
55 | "element-ui": "^2.0.10",
56 | "eslint": "^3.19.0",
57 | "eslint-config-standard": "^10.2.1",
58 | "eslint-friendly-formatter": "^3.0.0",
59 | "eslint-loader": "^1.7.1",
60 | "eslint-plugin-html": "^3.0.0",
61 | "eslint-plugin-import": "^2.7.0",
62 | "eslint-plugin-node": "^5.2.0",
63 | "eslint-plugin-promise": "^3.4.0",
64 | "eslint-plugin-standard": "^3.0.1",
65 | "extract-text-webpack-plugin": "^3.0.0",
66 | "file-loader": "^1.1.6",
67 | "friendly-errors-webpack-plugin": "^1.6.1",
68 | "html-minifier": "^3.5.9",
69 | "html-webpack-plugin": "^2.30.1",
70 | "jest": "^21.2.0",
71 | "jest-serializer-vue": "^0.3.0",
72 | "nightwatch": "^0.9.12",
73 | "node-notifier": "^5.1.2",
74 | "node-sass": "^4.7.2",
75 | "optimize-css-assets-webpack-plugin": "^3.2.0",
76 | "ora": "^1.2.0",
77 | "portfinder": "^1.0.13",
78 | "postcss-import": "^11.0.0",
79 | "postcss-loader": "^2.0.8",
80 | "postcss-url": "^7.2.1",
81 | "rimraf": "^2.6.0",
82 | "sass-loader": "^6.0.6",
83 | "selenium-server": "^3.0.1",
84 | "semver": "^5.3.0",
85 | "shelljs": "^0.7.6",
86 | "style-loader": "^0.19.1",
87 | "uglifyjs-webpack-plugin": "^1.1.1",
88 | "url-loader": "^0.5.8",
89 | "vue-jest": "^1.0.2",
90 | "vue-loader": "^13.3.0",
91 | "vue-style-loader": "^3.0.1",
92 | "vue-template-compiler": "^2.5.2",
93 | "webpack": "^3.6.0",
94 | "webpack-bundle-analyzer": "^2.9.0",
95 | "webpack-dev-server": "^2.9.1",
96 | "webpack-merge": "^4.1.0"
97 | },
98 | "engines": {
99 | "node": ">= 6.0.0",
100 | "npm": ">= 3.0.0"
101 | },
102 | "browserslist": [
103 | "> 1%",
104 | "last 2 versions",
105 | "not ie <= 8"
106 | ]
107 | }
108 |
--------------------------------------------------------------------------------
/server/db.js:
--------------------------------------------------------------------------------
1 | // Schema、Model、Entity或者Documents的关系请牢记,Schema生成Model,Model创造Entity,Model和Entity都可对数据库操作造成影响,但Model比Entity更具操作性。
2 | const mongoose = require('mongoose');
3 | // 连接数据库 如果不自己创建 默认test数据库会自动生成
4 | mongoose.connect('mongodb://localhost/tao');
5 |
6 | // 为这次连接绑定事件
7 | const db = mongoose.connection;
8 | db.once('error',() => console.log('Mongo connection error'));
9 | db.once('open',() => console.log('Mongo connection successed'));
10 | /************** 定义模式Schema **************/
11 | // const loginSchema = mongoose.Schema({
12 | // account : String,
13 | // password : String
14 | // });
15 |
16 | //user
17 | const userSchema = new mongoose.Schema({
18 | name: String,
19 | password: String,
20 | nickName: String,
21 | type: String,//1管理员,2游客
22 | token: String,
23 | avatar: String
24 | })
25 | //文章
26 | const articleSchema = new mongoose.Schema({
27 | title: String,
28 | date: String,
29 | category: Array,
30 | gist: String,
31 | content: String,
32 | comments: Array
33 | })
34 | //demo
35 | const demoSchema = new mongoose.Schema({
36 | title: String,
37 | date: String,
38 | file: String,
39 | pic: String,
40 | gist: String,
41 | })
42 | /************** 定义模型Model **************/
43 | // const Models = {
44 | // Login : mongoose.model('Login',loginSchema)
45 | // }
46 |
47 | const Models = {
48 | User: mongoose.model('User', userSchema),
49 | Article: mongoose.model('Article', articleSchema),
50 | Demo: mongoose.model('Demo', demoSchema)
51 | }
52 |
53 | module.exports = Models;
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const bodyParser = require('body-parser')
4 | const cors = require('cors');
5 | const express = require('express');
6 | const api = require('./api');
7 | const app = express();
8 | // const cookieParser=require('cookie-parser');
9 | const session=require('express-session');
10 |
11 | //跨域
12 | app.use(cors());
13 | // app.use(cookieParser());
14 | app.use(express.json({limit: '5mb'}));
15 | // app.use(session({
16 | // secret:'12345',
17 | // cookie:{maxAge:60 * 1000 * 60},
18 | // resave:false,
19 | // saveUninitialized:true
20 | // }))
21 |
22 | app.use(bodyParser.json());
23 | //当extended为false的时候,键值对中的值就为'String'或'Array'形式,为true的时候,则可为任何数据类型。
24 | app.use(bodyParser.urlencoded({extended: false}));
25 | app.use(api);
26 |
27 | // 监听8088端口
28 | app.listen(8088);
29 | console.log('success listen…………');
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/src/assets/logo.png
--------------------------------------------------------------------------------
/src/components/commonFooter.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
48 |
49 |
111 |
--------------------------------------------------------------------------------
/src/components/commonHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TaoLand
6 |
7 |
25 |
26 |
27 |
28 |
29 |
![]()
30 |
31 |
32 |
33 |
34 | - Home
35 | - Archives
36 | - Categories
37 | - Collections
38 | - Demo
39 | - About
40 | - {{nickName}}
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
89 |
90 |
188 |
--------------------------------------------------------------------------------
/src/components/commonLayout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
35 |
36 |
64 |
--------------------------------------------------------------------------------
/src/components/list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
![]()
6 |
7 |
11 |
12 |
13 |
14 |
15 |
20 |
21 |
79 |
--------------------------------------------------------------------------------
/src/components/list_article.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{item.type}}
5 |
24 |
25 |
26 |
27 |
28 |
55 |
56 |
140 |
--------------------------------------------------------------------------------
/src/components/list_content.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
37 |
38 |
62 |
--------------------------------------------------------------------------------
/src/components/list_home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{item.title}}
6 | {{item.gist}}
7 |
8 |
{{item.date}}
9 |
10 |
11 |
12 |
13 |
29 |
30 |
67 |
--------------------------------------------------------------------------------
/src/components/message.vue:
--------------------------------------------------------------------------------
1 |
2 | 我是详情页0419
3 |
4 |
5 |
9 |
10 |
12 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | // import VueResource from 'vue-resource'
3 | import axios from 'axios'
4 | import router from './router/index'
5 | import store from './store/index'
6 | import '../static/js/animation.js'
7 | import '../static/js/tween.js'
8 | // import '../static/live2d/live2d_something.js'
9 | // import '../static/live2d/live2d.js'
10 | import '../static/css/normalize.css'
11 | import '../static/css/public.css'
12 | import '../static/css/font/iconfont.css'
13 | import ElementUI from 'element-ui'
14 | import 'element-ui/lib/theme-chalk/index.css'
15 | import 'element-ui/lib/theme-chalk/display.css';
16 | import mavonEditor from 'mavon-editor'
17 | import 'mavon-editor/dist/css/index.css'
18 |
19 |
20 | // Vue.use(VueResource)
21 | Vue.prototype.$axios = axios
22 | Vue.use(ElementUI)
23 | Vue.use(mavonEditor)
24 |
25 | new Vue({
26 | el: '#app',
27 | data () {
28 | return {
29 | }
30 | },
31 | router,
32 | // axios,
33 | store,
34 | // watch:{
35 | // '$route'(to,from){
36 | // console.log(to)
37 | // }
38 | // }
39 | })
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/pages/about.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
About
8 |
9 |
10 |
关于我
11 |
做前端有2年了,目前就职于北京思源时代
12 |
并不是科班出身,学的是物理,后来从事不喜欢的工作,直到遇到前端
13 |
非常喜欢,开始自学,遇到过很多坑,但是一直坚持,坚信终有一天自己也会变强!
14 |
15 |
26 |
27 |
关于本站
28 |
这个博客主要用于记录一个菜鸟程序猿的Growth之路.
29 |
这也是自己第一次做博客,希望和大家多多交流,一起成长!
30 |
欢迎大家提一些对本站的建议,可以直接在下面留言或者新建一个Issue.
31 |
32 | - 实现了用户注册、登录、检测登录、博客管理(文章的修改和删除)、文章编辑(Markdown)、标签分类等功能。
33 | - 前端使用vue全家桶(cli,router,vuex,axios),框架用的elmentUI
34 | - 后端使用node,框架用的express,mongoose
35 | - 数据库采用mongodb
36 | - 服务器是centos的
37 |
38 |
39 |
Update Log
40 |
2018.2.28 v1.0.1
41 |
44 |
2018.3.20 v1.1.1
45 |
46 | [+]
新增流量统计功能
47 | [+]
新增token功能
48 | [+]
升到https
49 | [+]
若干bug
50 |
51 |
2018.6.10 v1.2.1
52 |
53 | [+]
大幅提高首页渲染速度
54 | [+]
看板娘上线
55 | [+]
若干优化
56 |
57 |
2018.7.23 v1.3.1
58 |
59 | [+]
游客登陆/注册/检测
60 | [+]
图片上传
61 | [+]
评论留言
62 | [+]
文章分享功能
63 | [+]
上一篇下一篇
64 |
65 |
73 |
74 |
75 |
86 |
87 |
88 |
89 |
90 |
Content
91 |
92 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
167 |
168 |
270 |
292 |
293 |
--------------------------------------------------------------------------------
/src/pages/admin/articleEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 返回
5 |
6 |
标题
7 |
8 |
9 |
分类
10 |
11 | {{category}}
12 |
13 |
14 |
简介
15 |
20 |
21 |
内容 (Markdown编辑器)
22 |
23 |
24 |
25 |
26 | 保存
27 |
28 |
29 |
30 |
31 |
171 |
172 |
--------------------------------------------------------------------------------
/src/pages/admin/articleList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
返回首页
4 |
{{type=='article'?'文章列表':'demo列表'}}
5 |
6 |
7 | Article
8 | Demo
9 |
10 |
11 |
12 | 新增+
13 |
19 |
22 |
23 | {{ scope.row.title }}
24 |
25 |
26 |
29 |
30 |
31 | {{ scope.row.date }}
32 |
33 |
34 |
37 |
38 | {{ scope.row.gist.slice(0,30) }}
39 |
40 |
41 |
44 |
45 | 未分类
46 | {{ tag }}
47 |
48 |
49 |
50 |
51 | 查看
55 | 编辑
59 | 删除
63 |
64 |
65 |
66 |
67 |
68 |
69 | 新增+
70 |
76 |
79 |
80 | {{ scope.row.title }}
81 |
82 |
83 |
86 |
87 |
88 | {{ scope.row.date }}
89 |
90 |
91 |
94 |
95 | {{ scope.row.file }}
96 |
97 |
98 |
101 |
102 | {{ scope.row.pic }}
103 |
104 |
105 |
108 |
109 | {{ scope.row.gist.slice(0,30) }}
110 |
111 |
112 |
113 |
114 | 查看
118 | 编辑
122 | 删除
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
273 |
274 |
275 |
280 |
--------------------------------------------------------------------------------
/src/pages/admin/demoEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 返回
5 |
6 |
标题
7 |
8 |
路径
9 |
10 |
图片
11 |
12 |
简介
13 |
18 |
19 |
20 | 保存
21 |
22 |
23 |
24 |
25 |
170 |
171 |
--------------------------------------------------------------------------------
/src/pages/archives.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
45 |
46 |
79 |
--------------------------------------------------------------------------------
/src/pages/categories.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
50 |
51 |
84 |
--------------------------------------------------------------------------------
/src/pages/collections.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Collections
8 |
9 |
{{item.type}}
10 |
16 |
17 |
18 |
19 |
20 |
21 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
75 |
76 |
195 |
--------------------------------------------------------------------------------
/src/pages/demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
![]()
8 |
9 |
{{item.title}}
10 |
{{item.gist}}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
38 |
39 |
203 |
--------------------------------------------------------------------------------
/src/pages/detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{title}}
5 |
6 | {{date}}
7 | {{tag}}
8 |
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
196 |
197 |
199 |
200 |
286 |
--------------------------------------------------------------------------------
/src/pages/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
ABOUT ME
14 |

15 |
16 |
行路有良友,便是捷径。带上我吧,一起去看更大的世界
17 |
23 |
24 |
25 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
63 |
64 |
129 |
--------------------------------------------------------------------------------
/src/pages/signin.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Sign In
7 |
New to Taoland ? Sign Up !
8 |
9 |
16 |
20 |
21 |
22 |
23 |
153 |
154 |
269 |
--------------------------------------------------------------------------------
/src/pages/visiter/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 昵称:
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 头像:
16 |
17 |
18 |
21 |
22 | tips:请上传2M以内JPG/PNG格式的图片,比例最好1:1
23 |
24 |
25 |
26 |
27 | Save
28 | Sign Out
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
136 |
137 |
212 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 |
4 | //前台
5 | // import CommonLayout from '@/components/commonLayout'
6 | // import Home from '@/pages/home'
7 | // import Archives from '@/pages/archives'
8 | // import Categories from '@/pages/categories'
9 | // import Collections from '@/pages/collections'
10 | // import Demo from '@/pages/demo'
11 | // import About from '@/pages/about'
12 | // import Detail from '@/pages/detail'
13 | const CommonLayout = r => require.ensure([], () => r(require('@/components/commonLayout')), 'chunkname1')
14 | const Home = r => require.ensure([], () => r(require('@/pages/home')), 'chunkname1')
15 | const Archives = r => require.ensure([], () => r(require('@/pages/archives')), 'chunkname1')
16 | const Categories = r => require.ensure([], () => r(require('@/pages/categories')), 'chunkname1')
17 | const Collections = r => require.ensure([], () => r(require('@/pages/collections')), 'chunkname1')
18 | const Demo = r => require.ensure([], () => r(require('@/pages/demo')), 'chunkname1')
19 | const About = r => require.ensure([], () => r(require('@/pages/about')), 'chunkname1')
20 | const Detail = r => require.ensure([], () => r(require('@/pages/detail')), 'chunkname2')
21 | const Signin = r => require.ensure([], () => r(require('@/pages/signin')), 'chunkname1')
22 |
23 |
24 | //admin后台
25 | // import Signin from '@/pages/admin/signin'
26 | // import ArticleList from '@/pages/admin/articleList'
27 | // import ArticleEdit from '@/pages/admin/articleEdit'
28 | // import DemoEdit from '@/pages/admin/demoEdit'
29 | const ArticleList = r => require.ensure([], () => r(require('@/pages/admin/articleList')), 'chunkname3')
30 | const ArticleEdit = r => require.ensure([], () => r(require('@/pages/admin/articleEdit')), 'chunkname3')
31 | const DemoEdit = r => require.ensure([], () => r(require('@/pages/admin/demoEdit')), 'chunkname3')
32 | //visiter后台
33 | const VisiterIndex = r => require.ensure([], () => r(require('@/pages/visiter/index')), 'chunkname3')
34 |
35 | Vue.use(VueRouter)
36 | const routes = [
37 | {
38 | path: '/',
39 | component: CommonLayout,
40 | // name:'layout',
41 | children:[
42 | {
43 | path: '',
44 | component: Home,
45 | name:'home'
46 | },
47 | {
48 | path: '/archives',
49 | component: Archives,
50 | name:'archives',
51 | },
52 | {
53 | path: '/detail/:id',
54 | component: Detail,
55 | },
56 | {
57 | path: '/categories',
58 | component: Categories,
59 | name:'categories'
60 | },
61 | {
62 | path: '/collections',
63 | component: Collections,
64 | name:'collections'
65 | },
66 | {
67 | path: '/demo',
68 | component: Demo,
69 | name:'demo'
70 | },
71 | {
72 | path: '/about',
73 | component: About,
74 | name:'about'
75 | },
76 | {
77 | path: '/visiter',
78 | component: VisiterIndex,
79 | name:'visiter'
80 | },
81 | ]
82 | },
83 | {
84 | path: '/sign',
85 | component: Signin,
86 | name:'Signin',
87 | alias: '/admin',
88 | },
89 | {
90 | path: '/admin/list',
91 | name: 'ArticleList',
92 | component: ArticleList
93 | },
94 | {
95 | path: '/admin/edit',
96 | name: 'ArticleEdit',
97 | component: ArticleEdit
98 | },
99 | {
100 | path: '/admin/edit/:id',
101 | name: 'ArticleUpdate',
102 | component: ArticleEdit
103 | },
104 | {
105 | path: '/admin/editt',
106 | name: 'DemoEdit',
107 | component: DemoEdit
108 | },
109 | {
110 | path: '/admin/editt/:id',
111 | name: 'DemoUpdate',
112 | component: DemoEdit
113 | }
114 | ]
115 | export default new VueRouter({
116 | // mode: 'history',
117 | routes
118 | })
119 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import { mapState } from 'vuex'
4 |
5 | Vue.use(Vuex)
6 |
7 | export default new Vuex.Store({
8 | state: {
9 | activeIndex: '1',//导航选中
10 | isSignIn: 0,//0未登录,1admin,2游客
11 | },
12 | mutations: {
13 | changeIndex(state, n) {
14 | state.activeIndex = n
15 | },
16 | changeIsSignIn(state, n) {
17 | state.isSignIn = n
18 | }
19 | }
20 | })
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/.gitkeep
--------------------------------------------------------------------------------
/static/css/font/demo.css:
--------------------------------------------------------------------------------
1 | *{margin: 0;padding: 0;list-style: none;}
2 | /*
3 | KISSY CSS Reset
4 | 理念:1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。
5 | 2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。
6 | 3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。
7 | 特色:1. 适应中文;2. 基于最新主流浏览器。
8 | 维护:玉伯, 正淳
9 | */
10 |
11 | /** 清除内外边距 **/
12 | body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */
13 | dl, dt, dd, ul, ol, li, /* list elements 列表元素 */
14 | pre, /* text formatting elements 文本格式元素 */
15 | form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */
16 | th, td /* table elements 表格元素 */ {
17 | margin: 0;
18 | padding: 0;
19 | }
20 |
21 | /** 设置默认字体 **/
22 | body,
23 | button, input, select, textarea /* for ie */ {
24 | font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif;
25 | }
26 | h1, h2, h3, h4, h5, h6 { font-size: 100%; }
27 | address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */
28 | code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */
29 | small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */
30 |
31 | /** 重置列表元素 **/
32 | ul, ol { list-style: none; }
33 |
34 | /** 重置文本格式元素 **/
35 | a { text-decoration: none; }
36 | a:hover { text-decoration: underline; }
37 |
38 |
39 | /** 重置表单元素 **/
40 | legend { color: #000; } /* for ie6 */
41 | fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */
42 | button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */
43 | /* 注:optgroup 无法扶正 */
44 |
45 | /** 重置表格元素 **/
46 | table { border-collapse: collapse; border-spacing: 0; }
47 |
48 | /* 清除浮动 */
49 | .ks-clear:after, .clear:after {
50 | content: '\20';
51 | display: block;
52 | height: 0;
53 | clear: both;
54 | }
55 | .ks-clear, .clear {
56 | *zoom: 1;
57 | }
58 |
59 | .main {
60 | padding: 30px 100px;
61 | width: 960px;
62 | margin: 0 auto;
63 | }
64 | .main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;}
65 |
66 | .helps{margin-top:40px;}
67 | .helps pre{
68 | padding:20px;
69 | margin:10px 0;
70 | border:solid 1px #e7e1cd;
71 | background-color: #fffdef;
72 | overflow: auto;
73 | }
74 |
75 | .icon_lists{
76 | width: 100% !important;
77 |
78 | }
79 |
80 | .icon_lists li{
81 | float:left;
82 | width: 100px;
83 | height:180px;
84 | text-align: center;
85 | list-style: none !important;
86 | }
87 | .icon_lists .icon{
88 | font-size: 42px;
89 | line-height: 100px;
90 | margin: 10px 0;
91 | color:#333;
92 | -webkit-transition: font-size 0.25s ease-out 0s;
93 | -moz-transition: font-size 0.25s ease-out 0s;
94 | transition: font-size 0.25s ease-out 0s;
95 |
96 | }
97 | .icon_lists .icon:hover{
98 | font-size: 100px;
99 | }
100 |
101 |
102 |
103 | .markdown {
104 | color: #666;
105 | font-size: 14px;
106 | line-height: 1.8;
107 | }
108 |
109 | .highlight {
110 | line-height: 1.5;
111 | }
112 |
113 | .markdown img {
114 | vertical-align: middle;
115 | max-width: 100%;
116 | }
117 |
118 | .markdown h1 {
119 | color: #404040;
120 | font-weight: 500;
121 | line-height: 40px;
122 | margin-bottom: 24px;
123 | }
124 |
125 | .markdown h2,
126 | .markdown h3,
127 | .markdown h4,
128 | .markdown h5,
129 | .markdown h6 {
130 | color: #404040;
131 | margin: 1.6em 0 0.6em 0;
132 | font-weight: 500;
133 | clear: both;
134 | }
135 |
136 | .markdown h1 {
137 | font-size: 28px;
138 | }
139 |
140 | .markdown h2 {
141 | font-size: 22px;
142 | }
143 |
144 | .markdown h3 {
145 | font-size: 16px;
146 | }
147 |
148 | .markdown h4 {
149 | font-size: 14px;
150 | }
151 |
152 | .markdown h5 {
153 | font-size: 12px;
154 | }
155 |
156 | .markdown h6 {
157 | font-size: 12px;
158 | }
159 |
160 | .markdown hr {
161 | height: 1px;
162 | border: 0;
163 | background: #e9e9e9;
164 | margin: 16px 0;
165 | clear: both;
166 | }
167 |
168 | .markdown p,
169 | .markdown pre {
170 | margin: 1em 0;
171 | }
172 |
173 | .markdown > p,
174 | .markdown > blockquote,
175 | .markdown > .highlight,
176 | .markdown > ol,
177 | .markdown > ul {
178 | width: 80%;
179 | }
180 |
181 | .markdown ul > li {
182 | list-style: circle;
183 | }
184 |
185 | .markdown > ul li,
186 | .markdown blockquote ul > li {
187 | margin-left: 20px;
188 | padding-left: 4px;
189 | }
190 |
191 | .markdown > ul li p,
192 | .markdown > ol li p {
193 | margin: 0.6em 0;
194 | }
195 |
196 | .markdown ol > li {
197 | list-style: decimal;
198 | }
199 |
200 | .markdown > ol li,
201 | .markdown blockquote ol > li {
202 | margin-left: 20px;
203 | padding-left: 4px;
204 | }
205 |
206 | .markdown code {
207 | margin: 0 3px;
208 | padding: 0 5px;
209 | background: #eee;
210 | border-radius: 3px;
211 | }
212 |
213 | .markdown pre {
214 | border-radius: 6px;
215 | background: #f7f7f7;
216 | padding: 20px;
217 | }
218 |
219 | .markdown pre code {
220 | border: none;
221 | background: #f7f7f7;
222 | margin: 0;
223 | }
224 |
225 | .markdown strong,
226 | .markdown b {
227 | font-weight: 600;
228 | }
229 |
230 | .markdown > table {
231 | border-collapse: collapse;
232 | border-spacing: 0px;
233 | empty-cells: show;
234 | border: 1px solid #e9e9e9;
235 | width: 95%;
236 | margin-bottom: 24px;
237 | }
238 |
239 | .markdown > table th {
240 | white-space: nowrap;
241 | color: #333;
242 | font-weight: 600;
243 |
244 | }
245 |
246 | .markdown > table th,
247 | .markdown > table td {
248 | border: 1px solid #e9e9e9;
249 | padding: 8px 16px;
250 | text-align: left;
251 | }
252 |
253 | .markdown > table th {
254 | background: #F7F7F7;
255 | }
256 |
257 | .markdown blockquote {
258 | font-size: 90%;
259 | color: #999;
260 | border-left: 4px solid #e9e9e9;
261 | padding-left: 0.8em;
262 | margin: 1em 0;
263 | font-style: italic;
264 | }
265 |
266 | .markdown blockquote p {
267 | margin: 0;
268 | }
269 |
270 | .markdown .anchor {
271 | opacity: 0;
272 | transition: opacity 0.3s ease;
273 | margin-left: 8px;
274 | }
275 |
276 | .markdown .waiting {
277 | color: #ccc;
278 | }
279 |
280 | .markdown h1:hover .anchor,
281 | .markdown h2:hover .anchor,
282 | .markdown h3:hover .anchor,
283 | .markdown h4:hover .anchor,
284 | .markdown h5:hover .anchor,
285 | .markdown h6:hover .anchor {
286 | opacity: 1;
287 | display: inline-block;
288 | }
289 |
290 | .markdown > br,
291 | .markdown > p > br {
292 | clear: both;
293 | }
294 |
295 |
296 | .hljs {
297 | display: block;
298 | background: white;
299 | padding: 0.5em;
300 | color: #333333;
301 | overflow-x: auto;
302 | }
303 |
304 | .hljs-comment,
305 | .hljs-meta {
306 | color: #969896;
307 | }
308 |
309 | .hljs-string,
310 | .hljs-variable,
311 | .hljs-template-variable,
312 | .hljs-strong,
313 | .hljs-emphasis,
314 | .hljs-quote {
315 | color: #df5000;
316 | }
317 |
318 | .hljs-keyword,
319 | .hljs-selector-tag,
320 | .hljs-type {
321 | color: #a71d5d;
322 | }
323 |
324 | .hljs-literal,
325 | .hljs-symbol,
326 | .hljs-bullet,
327 | .hljs-attribute {
328 | color: #0086b3;
329 | }
330 |
331 | .hljs-section,
332 | .hljs-name {
333 | color: #63a35c;
334 | }
335 |
336 | .hljs-tag {
337 | color: #333333;
338 | }
339 |
340 | .hljs-title,
341 | .hljs-attr,
342 | .hljs-selector-id,
343 | .hljs-selector-class,
344 | .hljs-selector-attr,
345 | .hljs-selector-pseudo {
346 | color: #795da3;
347 | }
348 |
349 | .hljs-addition {
350 | color: #55a532;
351 | background-color: #eaffea;
352 | }
353 |
354 | .hljs-deletion {
355 | color: #bd2c00;
356 | background-color: #ffecec;
357 | }
358 |
359 | .hljs-link {
360 | text-decoration: underline;
361 | }
362 |
363 | pre{
364 | background: #fff;
365 | }
366 |
367 |
368 |
369 |
370 |
371 |
--------------------------------------------------------------------------------
/static/css/font/demo_fontclass.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | IconFont
7 |
8 |
9 |
10 |
11 |
12 |
IconFont 图标
13 |
14 |
15 | -
16 |
17 |
分类
18 | .icon-tubiao13
19 |
20 |
21 | -
22 |
23 |
home
24 | .icon-home
25 |
26 |
27 | -
28 |
29 |
收藏
30 | .icon-shoucang
31 |
32 |
33 | -
34 |
35 |
关于我们
36 | .icon-guanyuwomen
37 |
38 |
39 | -
40 |
41 |
聊天-选中1
42 | .icon-liaotianxuanzhong1
43 |
44 |
45 | -
46 |
47 |
play
48 | .icon-play
49 |
50 |
51 | -
52 |
53 |
meho
54 | .icon-meho
55 |
56 |
57 | -
58 |
59 |
github
60 | .icon-github
61 |
62 |
63 | -
64 |
65 |
知乎
66 | .icon-zhihu
67 |
68 |
69 | -
70 |
71 |
top
72 | .icon-top
73 |
74 |
75 | -
76 |
77 |
关闭
78 | .icon-guanbi
79 |
80 |
81 | -
82 |
83 |
微博
84 | .icon-weibo
85 |
86 |
87 | -
88 |
89 |
衣服
90 | .icon-yifu
91 |
92 |
93 | -
94 |
95 |
音乐
96 | .icon-yinle
97 |
98 |
99 | -
100 |
101 |
date
102 | .icon-date
103 |
104 |
105 | -
106 |
107 |
archives
108 | .icon-archives
109 |
110 |
111 |
112 |
113 |
font-class引用
114 |
115 |
116 |
font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。
117 |
与unicode使用方式相比,具有如下特点:
118 |
119 | - 兼容性良好,支持ie8+,及所有现代浏览器。
120 | - 相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。
121 | - 因为使用class来定义图标,所以当要替换图标时,只需要修改class里面的unicode引用。
122 | - 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
123 |
124 |
使用步骤如下:
125 |
第一步:引入项目下面生成的fontclass代码:
126 |
127 |
128 |
129 |
第二步:挑选相应图标并获取类名,应用于页面:
130 |
<i class="iconfont icon-xxx"></i>
131 |
132 | "iconfont"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/static/css/font/demo_symbol.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | IconFont
7 |
8 |
9 |
10 |
24 |
25 |
26 |
27 |
IconFont 图标
28 |
29 |
30 | -
31 |
34 |
分类
35 | #icon-tubiao13
36 |
37 |
38 | -
39 |
42 |
home
43 | #icon-home
44 |
45 |
46 | -
47 |
50 |
收藏
51 | #icon-shoucang
52 |
53 |
54 | -
55 |
58 |
关于我们
59 | #icon-guanyuwomen
60 |
61 |
62 | -
63 |
66 |
聊天-选中1
67 | #icon-liaotianxuanzhong1
68 |
69 |
70 | -
71 |
74 |
play
75 | #icon-play
76 |
77 |
78 | -
79 |
82 |
meho
83 | #icon-meho
84 |
85 |
86 | -
87 |
90 |
github
91 | #icon-github
92 |
93 |
94 | -
95 |
98 |
知乎
99 | #icon-zhihu
100 |
101 |
102 | -
103 |
106 |
top
107 | #icon-top
108 |
109 |
110 | -
111 |
114 |
关闭
115 | #icon-guanbi
116 |
117 |
118 | -
119 |
122 |
微博
123 | #icon-weibo
124 |
125 |
126 | -
127 |
130 |
衣服
131 | #icon-yifu
132 |
133 |
134 | -
135 |
138 |
音乐
139 | #icon-yinle
140 |
141 |
142 | -
143 |
146 |
date
147 | #icon-date
148 |
149 |
150 | -
151 |
154 |
archives
155 | #icon-archives
156 |
157 |
158 |
159 |
160 |
161 |
symbol引用
162 |
163 |
164 |
这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章
165 | 这种用法其实是做了一个svg的集合,与另外两种相比具有如下特点:
166 |
167 | - 支持多色图标了,不再受单色限制。
168 | - 通过一些技巧,支持像字体那样,通过
font-size
,color
来调整样式。
169 | - 兼容性较差,支持 ie9+,及现代浏览器。
170 | - 浏览器渲染svg的性能一般,还不如png。
171 |
172 |
使用步骤如下:
173 |
第一步:引入项目下面生成的symbol代码:
174 |
175 |
第二步:加入通用css代码(引入一次就行):
176 |
<style type="text/css">
177 | .icon {
178 | width: 1em; height: 1em;
179 | vertical-align: -0.15em;
180 | fill: currentColor;
181 | overflow: hidden;
182 | }
183 | </style>
184 |
第三步:挑选相应图标并获取类名,应用于页面:
185 |
<svg class="icon" aria-hidden="true">
186 | <use xlink:href="#icon-xxx"></use>
187 | </svg>
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/static/css/font/demo_unicode.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | IconFont
7 |
8 |
9 |
29 |
30 |
31 |
32 |
IconFont 图标
33 |
34 |
35 | -
36 |
37 |
分类
38 | 
39 |
40 |
41 | -
42 |
43 |
home
44 | 
45 |
46 |
47 | -
48 |
49 |
收藏
50 | 
51 |
52 |
53 | -
54 |
55 |
关于我们
56 | 
57 |
58 |
59 | -
60 |
61 |
聊天-选中1
62 | 
63 |
64 |
65 | -
66 |
67 |
play
68 | 
69 |
70 |
71 | -
72 |
73 |
meho
74 | 
75 |
76 |
77 | -
78 |
79 |
github
80 | 
81 |
82 |
83 | -
84 |
85 |
知乎
86 | 
87 |
88 |
89 | -
90 |
91 |
top
92 | 
93 |
94 |
95 | -
96 |
97 |
关闭
98 | 
99 |
100 |
101 | -
102 |
103 |
微博
104 | 
105 |
106 |
107 | -
108 |
109 |
衣服
110 | 
111 |
112 |
113 | -
114 |
115 |
音乐
116 | 
117 |
118 |
119 | -
120 |
121 |
date
122 | 
123 |
124 |
125 | -
126 |
127 |
archives
128 | 
129 |
130 |
131 |
132 |
unicode引用
133 |
134 |
135 |
unicode是字体在网页端最原始的应用方式,特点是:
136 |
137 | - 兼容性最好,支持ie6+,及所有现代浏览器。
138 | - 支持按字体的方式去动态调整图标大小,颜色等等。
139 | - 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
140 |
141 |
142 | 注意:新版iconfont支持多色图标,这些多色图标在unicode模式下将不能使用,如果有需求建议使用symbol的引用方式
143 |
144 |
unicode使用步骤如下:
145 |
第一步:拷贝项目下面生成的font-face
146 |
@font-face {
147 | font-family: 'iconfont';
148 | src: url('iconfont.eot');
149 | src: url('iconfont.eot?#iefix') format('embedded-opentype'),
150 | url('iconfont.woff') format('woff'),
151 | url('iconfont.ttf') format('truetype'),
152 | url('iconfont.svg#iconfont') format('svg');
153 | }
154 |
155 |
第二步:定义使用iconfont的样式
156 |
.iconfont{
157 | font-family:"iconfont" !important;
158 | font-size:16px;font-style:normal;
159 | -webkit-font-smoothing: antialiased;
160 | -webkit-text-stroke-width: 0.2px;
161 | -moz-osx-font-smoothing: grayscale;
162 | }
163 |
164 |
第三步:挑选相应图标并获取字体编码,应用于页面
165 |
<i class="iconfont">3</i>
166 |
167 |
168 | "iconfont"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。
169 |
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/static/css/font/iconfont.css:
--------------------------------------------------------------------------------
1 |
2 | @font-face {font-family: "iconfont";
3 | src: url('iconfont.eot?t=1528623945803'); /* IE9*/
4 | src: url('iconfont.eot?t=1528623945803#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('iconfont.ttf?t=1528623945803') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
7 | url('iconfont.svg?t=1528623945803#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 |
18 | .icon-tubiao13:before { content: "\e60d"; }
19 |
20 | .icon-home:before { content: "\e64e"; }
21 |
22 | .icon-shoucang:before { content: "\e646"; }
23 |
24 | .icon-guanyuwomen:before { content: "\e61e"; }
25 |
26 | .icon-liaotianxuanzhong1:before { content: "\e604"; }
27 |
28 | .icon-play:before { content: "\e603"; }
29 |
30 | .icon-meho:before { content: "\ee99"; }
31 |
32 | .icon-github:before { content: "\eee2"; }
33 |
34 | .icon-zhihu:before { content: "\e69a"; }
35 |
36 | .icon-top:before { content: "\e615"; }
37 |
38 | .icon-guanbi:before { content: "\e638"; }
39 |
40 | .icon-weibo:before { content: "\e699"; }
41 |
42 | .icon-yifu:before { content: "\e678"; }
43 |
44 | .icon-yinle:before { content: "\e61d"; }
45 |
46 | .icon-date:before { content: "\e78a"; }
47 |
48 | .icon-archives:before { content: "\e622"; }
49 |
50 |
--------------------------------------------------------------------------------
/static/css/font/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/css/font/iconfont.eot
--------------------------------------------------------------------------------
/static/css/font/iconfont.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/css/font/iconfont.js.gz
--------------------------------------------------------------------------------
/static/css/font/iconfont.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
82 |
--------------------------------------------------------------------------------
/static/css/font/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/css/font/iconfont.ttf
--------------------------------------------------------------------------------
/static/css/font/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/css/font/iconfont.woff
--------------------------------------------------------------------------------
/static/css/normalize.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-family: sans-serif; /* 1 */
3 | line-height: 1.15; /* 2 */
4 | -ms-text-size-adjust: 100%; /* 3 */
5 | -webkit-text-size-adjust: 100%; /* 3 */
6 | }
7 | body {
8 | margin: 0;
9 | }
10 | article,
11 | aside,
12 | footer,
13 | header,
14 | nav,
15 | section {
16 | display: block;
17 | }
18 | h1 {
19 | font-size: 2em;
20 | margin: 0.67em 0;
21 | }
22 | figcaption,
23 | figure,
24 | main { /* 1 */
25 | display: block;
26 | }
27 | figure {
28 | margin: 1em 40px;
29 | }
30 | hr {
31 | box-sizing: content-box; /* 1 */
32 | height: 0; /* 1 */
33 | overflow: visible; /* 2 */
34 | }
35 | pre {
36 | font-family: monospace, monospace; /* 1 */
37 | font-size: 1em; /* 2 */
38 | }
39 | a {
40 | background-color: transparent; /* 1 */
41 | -webkit-text-decoration-skip: objects; /* 2 */
42 | }
43 | a:active,
44 | a:hover {
45 | outline-width: 0;
46 | }
47 | abbr[title] {
48 | border-bottom: none; /* 1 */
49 | text-decoration: underline; /* 2 */
50 | text-decoration: underline dotted; /* 2 */
51 | }
52 | b,
53 | strong {
54 | font-weight: inherit;
55 | }
56 | b,
57 | strong {
58 | font-weight: bolder;
59 | }
60 | code,
61 | kbd,
62 | samp {
63 | font-family: monospace, monospace; /* 1 */
64 | font-size: 1em; /* 2 */
65 | }
66 | dfn {
67 | font-style: italic;
68 | }
69 | mark {
70 | background-color: #ff0;
71 | color: #000;
72 | }
73 | small {
74 | font-size: 80%;
75 | }
76 | sub,
77 | sup {
78 | font-size: 75%;
79 | line-height: 0;
80 | position: relative;
81 | vertical-align: baseline;
82 | }
83 | sub {
84 | bottom: -0.25em;
85 | }
86 | sup {
87 | top: -0.5em;
88 | }
89 | audio,
90 | video {
91 | display: inline-block;
92 | }
93 | audio:not([controls]) {
94 | display: none;
95 | height: 0;
96 | }
97 | img {
98 | border-style: none;
99 | }
100 | svg:not(:root) {
101 | overflow: hidden;
102 | }
103 | button,
104 | input,
105 | optgroup,
106 | select,
107 | textarea {
108 | font-family: sans-serif; /* 1 */
109 | font-size: 100%; /* 1 */
110 | line-height: 1.15; /* 1 */
111 | margin: 0; /* 2 */
112 | }
113 | button,
114 | input { /* 1 */
115 | overflow: visible;
116 | }
117 | button,
118 | select { /* 1 */
119 | text-transform: none;
120 | }
121 | button,
122 | html [type="button"], /* 1 */
123 | [type="reset"],
124 | [type="submit"] {
125 | -webkit-appearance: button; /* 2 */
126 | }
127 | button::-moz-focus-inner,
128 | [type="button"]::-moz-focus-inner,
129 | [type="reset"]::-moz-focus-inner,
130 | [type="submit"]::-moz-focus-inner {
131 | border-style: none;
132 | padding: 0;
133 | }
134 | button:-moz-focusring,
135 | [type="button"]:-moz-focusring,
136 | [type="reset"]:-moz-focusring,
137 | [type="submit"]:-moz-focusring {
138 | outline: 1px dotted ButtonText;
139 | }
140 | fieldset {
141 | border: 1px solid #c0c0c0;
142 | margin: 0 2px;
143 | padding: 0.35em 0.625em 0.75em;
144 | }
145 | legend {
146 | box-sizing: border-box; /* 1 */
147 | color: inherit; /* 2 */
148 | display: table; /* 1 */
149 | max-width: 100%; /* 1 */
150 | padding: 0; /* 3 */
151 | white-space: normal; /* 1 */
152 | }
153 | progress {
154 | display: inline-block; /* 1 */
155 | vertical-align: baseline; /* 2 */
156 | }
157 | textarea {
158 | overflow: auto;
159 | }
160 | [type="checkbox"],
161 | [type="radio"] {
162 | box-sizing: border-box; /* 1 */
163 | padding: 0; /* 2 */
164 | }
165 | [type="number"]::-webkit-inner-spin-button,
166 | [type="number"]::-webkit-outer-spin-button {
167 | height: auto;
168 | }
169 | [type="search"] {
170 | -webkit-appearance: textfield; /* 1 */
171 | outline-offset: -2px; /* 2 */
172 | }
173 | [type="search"]::-webkit-search-cancel-button,
174 | [type="search"]::-webkit-search-decoration {
175 | -webkit-appearance: none;
176 | }
177 | ::-webkit-file-upload-button {
178 | -webkit-appearance: button; /* 1 */
179 | font: inherit; /* 2 */
180 | }
181 | details, /* 1 */
182 | menu {
183 | display: block;
184 | }
185 | summary {
186 | display: list-item;
187 | }
188 | canvas {
189 | display: inline-block;
190 | }
191 | template {
192 | display: none;
193 | }
194 | [hidden] {
195 | display: none;
196 | }
197 | /*add*/
198 | ul{margin: 0;padding: 0;}
199 | a{text-decoration: none;}
200 | p{margin: 0;}
201 | h1{margin:0;}
202 |
--------------------------------------------------------------------------------
/static/css/public.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 | /* CSS Document */
3 | body { box-sizing: content-box; font: normal 14px/1.5 \5fae\8f6f\96c5\9ed1, Microsoft YaHei, \5b8b\4f53 ;background-color: #fff; }
4 | /*解决:滚动条有无产生的跳动*/
5 | html {overflow-y: scroll;}
6 | :root {overflow-y: auto;overflow-x: hidden;}
7 | :root body {position: absolute;}
8 | body {width: 100vw;min-height: 100%;overflow: hidden;background: url(../img/bg.jpg);}
9 | body.admin{background:url('../img/bg_admin.jpg');}
10 | @media (min-width: 768px) {body.admin{background-size: cover;}}
11 | /*合并表格的border*/
12 | /* table { border-collapse: collapse; border-spacing: 0; } */
13 | img {-ms-interpolation-mode: bicubic; }
14 | /* ul li { list-style-type: none;} */
15 | input, textarea {color: inherit;font-size: inherit; font-family: inherit;}
16 | #app>.container>.page{min-height:calc(100vh - 262px);}
17 | /* 设置滚动条的样式 */
18 | ::-webkit-scrollbar{width:8px;background-color:#aeaeae;}
19 | /* 滚动槽 */
20 | ::-webkit-scrollbar-track-piece{width:8px;background-color:#f8f8f8;}
21 | /* 滚动条滑块 */
22 | ::-webkit-scrollbar-thumb{width:8px;background-color:#00C0FF;min-height: 88px}
23 | ::-webkit-scrollbar-thumb:hover{ width:8px; background-color:#aeaeae;}
24 | /*打印*/
25 | @media print {
26 | img { max-width: 100% !important; }
27 | p, h2, h3 { orphans: 3; widows: 3; }
28 | }
29 | /*不能拖拽*/
30 | textarea { resize: none; }
31 | /*去掉默认边框*/
32 | input,
33 | button,
34 | select,
35 | textarea,
36 | a { outline: none;color: #666666;}
37 | /* 只支持IE,过多使用效率低 */
38 | a { blr: expression(this.onFocus=this.close()); blr: expression(this.onFocus=this.blur()); }
39 | /* IE不支持 */
40 | a:focus { -moz-outline-style: none; outline: none; }
41 | /*清除浮动*/
42 | /*父级*/
43 | .clearfix:after { height: 0; content: ""; display: block; clear: both; visibility: hidden; font-size: 0; }
44 | .clearfix { zoom: 1; }
45 | /* 子级 */
46 | .clear { clear: both; height: 0; font-size: 0; }
47 | /*常用快捷*/
48 | .yahei { font-family: 'Microsoft YaHei'; }
49 | .songti { font-family: 'Arial'; }
50 | .fl { float: left; }
51 | .fr { float: right; }
52 | .nmr{margin-right: 0!important;}
53 | .nml{margin-left: 0!important;}
54 | .nmb{margin-bottom: 0!important;}
55 | .nmt{margin-top: 0!important;}
56 | .nomore{white-space: nowrap;text-overflow:ellipsis; overflow:hidden;}
57 | .trans{ -webkit-transition:all .3s linear; transition:all .3s linear; }
58 | /* 大小不定元素垂直居中 让子inline-block化,再在后面添加一个隐藏的垂直居中的inline-block元素实现*/
59 | .dib-vm{display:inline-block;*display:inline;*zoom:1;width:0; height:100%; vertical-align:middle;}
60 | .wrapper{max-width: 1200px; margin:0 auto;}
61 | /*字体选中颜色*/
62 | ::selection{background: #0074D9;color: #fff;}
63 | ::-moz-selection{background: #0074D9;color: #fff;}
64 |
65 |
66 | /*markdown 编辑器 */
67 | .v-show-content{
68 | background: #fff!important;
69 | }
--------------------------------------------------------------------------------
/static/img/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/img/avatar.png
--------------------------------------------------------------------------------
/static/img/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/img/bg.jpg
--------------------------------------------------------------------------------
/static/img/bg_admin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/img/bg_admin.jpg
--------------------------------------------------------------------------------
/static/img/p1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/img/p1.png
--------------------------------------------------------------------------------
/static/img/tao.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/img/tao.ico
--------------------------------------------------------------------------------
/static/js/animation.js:
--------------------------------------------------------------------------------
1 | // 对运动方法进行封装
2 | Math.animation = function (from, to, duration, easing, callback) {
3 | var isUndefined = function (obj) {
4 | return typeof obj == 'undefined';
5 | };
6 | var isFunction = function (obj) {
7 | return typeof obj == 'function';
8 | };
9 | var isNumber = function(obj) {
10 | return typeof obj == 'number';
11 | };
12 | var isString = function(obj) {
13 | return typeof obj == 'string';
14 | };
15 |
16 | // 转换成毫秒
17 | var toMillisecond = function(obj) {
18 | if (isNumber(obj)) {
19 | return obj;
20 | } else if (isString(obj)) {
21 | if (/\d+m?s$/.test(obj)) {
22 | if (/ms/.test(obj)) {
23 | return 1 * obj.replace('ms', '');
24 | }
25 | return 1000 * obj.replace('s', '');
26 | } else if (/^\d+$/.test(obj)) {
27 | return +obj;
28 | }
29 | }
30 | return -1;
31 | };
32 |
33 | if (!isNumber(from) || !isNumber(to)) {
34 | if (window.console) {
35 | console.error('from和to两个参数必须且为数值');
36 | }
37 | return 0;
38 | }
39 |
40 | // 缓动算法
41 | var tween = Math.tween || window.Tween;
42 |
43 | if (!tween) {
44 | if (window.console) {
45 | console.error('缓动算法函数缺失');
46 | }
47 | return 0;
48 | }
49 |
50 | // duration, easing, callback均为可选参数
51 | // 而且顺序可以任意
52 | var options = {
53 | duration: 300,
54 | easing: 'Linear',
55 | callback: function() {}
56 | };
57 |
58 | var setOptions = function(obj) {
59 | if (isFunction(obj)) {
60 | options.callback = obj;
61 | } else if (toMillisecond(obj) != -1) {
62 | options.duration = toMillisecond(obj);
63 | } else if (isString(obj)) {
64 | options.easing = obj;
65 | }
66 | };
67 | setOptions(duration);
68 | setOptions(easing);
69 | setOptions(callback);
70 |
71 | // requestAnimationFrame的兼容处理
72 | if (!window.requestAnimationFrame) {
73 | requestAnimationFrame = function (fn) {
74 | setTimeout(fn, 17);
75 | };
76 | }
77 |
78 | // 算法需要的几个变量
79 | var start = 0;
80 | // during根据设置的总时间计算
81 | var during = Math.ceil(options.duration / 17);
82 |
83 | // 当前动画算法
84 | // 确保首字母大写
85 | options.easing = options.easing.slice(0, 1).toUpperCase() + options.easing.slice(1);
86 | var arrKeyTween = options.easing.split('.');
87 | var fnGetValue;
88 |
89 | if (arrKeyTween.length == 1) {
90 | fnGetValue = tween[arrKeyTween[0]];
91 | } else if (arrKeyTween.length == 2) {
92 | fnGetValue = tween[arrKeyTween[0]] && tween[arrKeyTween[0]][arrKeyTween[1]];
93 | }
94 | if (isFunction(fnGetValue) == false) {
95 | console.error('没有找到名为"'+ options.easing +'"的动画算法');
96 | return;
97 | }
98 |
99 | // 运动
100 | var step = function() {
101 | // 当前的运动位置
102 | var value = fnGetValue(start, from, to - from, during);
103 |
104 | // 时间递增
105 | start++;
106 | // 如果还没有运动到位,继续
107 | if (start <= during) {
108 | options.callback(value);
109 | requestAnimationFrame(step);
110 | } else {
111 | // 动画结束,这里可以插入回调...
112 | options.callback(to, true);
113 | }
114 | };
115 | // 开始执行动画
116 | step();
117 | };
--------------------------------------------------------------------------------
/static/js/public.js:
--------------------------------------------------------------------------------
1 | //ip
2 | export const webUrl = '/api/'
3 |
4 |
5 |
6 |
7 | //公用方法========================================================================================
8 |
9 | /**
10 | * 模拟锚点
11 | */
12 | export const anchor = {
13 | created: function () {
14 | },
15 | methods: {
16 | anchor: function (e) {
17 | let id = 'anchor-' + e;
18 | let anchor = document.getElementById(id);
19 | let go = anchor.offsetTop;
20 |
21 | // console.log(go)
22 | Math.animation(document.documentElement.scrollTop, go, 800, 'Quart.easeOut', function (value) {
23 | document.documentElement.scrollTop = value;
24 | });
25 | }
26 | }
27 | }
28 | /**
29 | * imgFile=>base64
30 | * .toDataURL()方法应该写在
的onload事件中,以确保 canvas 的绘制工作在图片下载完成后开始。
31 | */
32 | export const imgTo64 = (img) => {
33 | let canvas = document.createElement("canvas");
34 | let width = img.width;
35 | let height = img.height;
36 |
37 | if (width > height) {
38 | if (width > 100) {
39 | width = Math.round(width * 100 / height);
40 | height = 100
41 | }
42 | } else {
43 | if (height > 100) {
44 | height = Math.round(height * 100 / width);
45 | width = 100
46 | }
47 | }
48 | canvas.width = width; /*设置新的图片的宽度*/
49 | canvas.height = height; /*设置新的图片的长度*/
50 | let ctx = canvas.getContext("2d");
51 | ctx.drawImage(img, 0, 0, width, height); /*绘图*/
52 | let dataURL = canvas.toDataURL("image/png", 0.8);
53 | // return dataURL.replace("data:image/png;base64,", "");
54 | return dataURL;
55 | }
56 |
57 | /**
58 | * Guid
59 | */
60 | export const Guid = () => {
61 | function S4() {
62 | return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
63 | }
64 | return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
65 | }
66 | /**
67 | * getDate
68 | */
69 | export const getDate = () => {
70 | let mydate, y, m, d, hh, mm, ss;
71 | mydate = new Date()
72 | y = mydate.getFullYear()
73 | m = mydate.getMonth() + 1
74 | d = mydate.getDate()
75 | hh = mydate.getHours()
76 | mm = mydate.getMinutes()
77 | ss = mydate.getSeconds()
78 | if (m < 10) m = '0' + m
79 | if (d < 10) d = '0' + d
80 | if (hh < 10) hh = '0' + hh
81 | if (mm < 10) mm = '0' + mm
82 | if (ss < 10) ss = '0' + ss
83 | return y + '-' + m + '-' + d + ' ' + hh + ':' + mm + ':' + ss
84 | }
85 |
86 | //mixins========================================================================================
87 |
88 | //checkAdmin 检测admin
89 | export const checkAdmin = {
90 | beforeCreate: function () {
91 | let user_name = localStorage.getItem("user_name");
92 | let token = localStorage.getItem("token");
93 | this.$axios.post(webUrl + 'admin/checkUser', { 'user_name': user_name, 'token': token })
94 | .then((response) => {
95 | if (response.data.status == 0) {
96 | this.$store.commit("changeIsSignIn", 0);
97 | this.$store.commit("changeIndex", '1');
98 | localStorage.clear();
99 | this.$router.replace({ name: 'home' })
100 | } else {
101 | if (response.data.type == 1) {
102 | this.$store.commit("changeIsSignIn", 1);//admin
103 | } else if (response.data.type == 2) {
104 | this.$store.commit("changeIsSignIn", 2);//游客
105 | this.$router.replace({ name: 'home' })
106 | this.$store.commit("changeIndex", '1');
107 | }
108 | }
109 | })
110 | .catch((reject) => {
111 | console.log(reject)
112 | })
113 | }
114 | }
115 | //checkVisiter 检测游客
116 | export const checkVisiter = {
117 | beforeCreate: function () {
118 | let user_name = localStorage.getItem("user_name");
119 | let token = localStorage.getItem("token");
120 | this.$axios.post(webUrl + 'admin/checkUser', { 'user_name': user_name, 'token': token })
121 | .then((response) => {
122 | if (response.data.status == 0) {
123 | this.$store.commit("changeIsSignIn", 0);
124 | this.$store.commit("changeIndex", '1');
125 | localStorage.clear();
126 | this.$router.replace({ name: 'home' })
127 | }
128 | })
129 | .catch((reject) => {
130 | console.log(reject)
131 | })
132 | }
133 | }
134 | //checkSign登陆情况
135 | export const checkSign = {
136 | beforeCreate: function () {
137 | let user_name = localStorage.getItem("user_name");
138 | let token = localStorage.getItem("token");
139 | this.$axios.post(webUrl + 'admin/checkUser', { 'user_name': user_name, 'token': token })
140 | .then((response) => {
141 | if (response.data.status == 0) {
142 | this.$store.commit("changeIsSignIn", 0);
143 | localStorage.clear();
144 | } else {
145 | if (response.data.type == 1) {
146 | this.$store.commit("changeIsSignIn", 1);//admin
147 | } else if (response.data.type == 2) {
148 | this.$store.commit("changeIsSignIn", 2);//游客
149 | }
150 | }
151 | })
152 | .catch((reject) => {
153 | console.log(reject)
154 | })
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/static/js/tween.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Tween.js
3 | * t: current time(当前时间);
4 | * b: beginning value(初始值);
5 | * c: change in value(变化量);
6 | * d: duration(持续时间)。
7 | * you can visit 'http://easings.net/zh-cn' to get effect
8 | */
9 | var Tween = {
10 | Linear: function(t, b, c, d) { return c*t/d + b; },
11 | Quad: {
12 | easeIn: function(t, b, c, d) {
13 | return c * (t /= d) * t + b;
14 | },
15 | easeOut: function(t, b, c, d) {
16 | return -c *(t /= d)*(t-2) + b;
17 | },
18 | easeInOut: function(t, b, c, d) {
19 | if ((t /= d / 2) < 1) return c / 2 * t * t + b;
20 | return -c / 2 * ((--t) * (t-2) - 1) + b;
21 | }
22 | },
23 | Cubic: {
24 | easeIn: function(t, b, c, d) {
25 | return c * (t /= d) * t * t + b;
26 | },
27 | easeOut: function(t, b, c, d) {
28 | return c * ((t = t/d - 1) * t * t + 1) + b;
29 | },
30 | easeInOut: function(t, b, c, d) {
31 | if ((t /= d / 2) < 1) return c / 2 * t * t*t + b;
32 | return c / 2*((t -= 2) * t * t + 2) + b;
33 | }
34 | },
35 | Quart: {
36 | easeIn: function(t, b, c, d) {
37 | return c * (t /= d) * t * t*t + b;
38 | },
39 | easeOut: function(t, b, c, d) {
40 | return -c * ((t = t/d - 1) * t * t*t - 1) + b;
41 | },
42 | easeInOut: function(t, b, c, d) {
43 | if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
44 | return -c / 2 * ((t -= 2) * t * t*t - 2) + b;
45 | }
46 | },
47 | Quint: {
48 | easeIn: function(t, b, c, d) {
49 | return c * (t /= d) * t * t * t * t + b;
50 | },
51 | easeOut: function(t, b, c, d) {
52 | return c * ((t = t/d - 1) * t * t * t * t + 1) + b;
53 | },
54 | easeInOut: function(t, b, c, d) {
55 | if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
56 | return c / 2*((t -= 2) * t * t * t * t + 2) + b;
57 | }
58 | },
59 | Sine: {
60 | easeIn: function(t, b, c, d) {
61 | return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
62 | },
63 | easeOut: function(t, b, c, d) {
64 | return c * Math.sin(t/d * (Math.PI/2)) + b;
65 | },
66 | easeInOut: function(t, b, c, d) {
67 | return -c / 2 * (Math.cos(Math.PI * t/d) - 1) + b;
68 | }
69 | },
70 | Expo: {
71 | easeIn: function(t, b, c, d) {
72 | return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
73 | },
74 | easeOut: function(t, b, c, d) {
75 | return (t==d) ? b + c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
76 | },
77 | easeInOut: function(t, b, c, d) {
78 | if (t==0) return b;
79 | if (t==d) return b+c;
80 | if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
81 | return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
82 | }
83 | },
84 | Circ: {
85 | easeIn: function(t, b, c, d) {
86 | return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
87 | },
88 | easeOut: function(t, b, c, d) {
89 | return c * Math.sqrt(1 - (t = t/d - 1) * t) + b;
90 | },
91 | easeInOut: function(t, b, c, d) {
92 | if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
93 | return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
94 | }
95 | },
96 | Elastic: {
97 | easeIn: function(t, b, c, d, a, p) {
98 | var s;
99 | if (t==0) return b;
100 | if ((t /= d) == 1) return b + c;
101 | if (typeof p == "undefined") p = d * .3;
102 | if (!a || a < Math.abs(c)) {
103 | s = p / 4;
104 | a = c;
105 | } else {
106 | s = p / (2 * Math.PI) * Math.asin(c / a);
107 | }
108 | return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
109 | },
110 | easeOut: function(t, b, c, d, a, p) {
111 | var s;
112 | if (t==0) return b;
113 | if ((t /= d) == 1) return b + c;
114 | if (typeof p == "undefined") p = d * .3;
115 | if (!a || a < Math.abs(c)) {
116 | a = c;
117 | s = p / 4;
118 | } else {
119 | s = p/(2*Math.PI) * Math.asin(c/a);
120 | }
121 | return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
122 | },
123 | easeInOut: function(t, b, c, d, a, p) {
124 | var s;
125 | if (t==0) return b;
126 | if ((t /= d / 2) == 2) return b+c;
127 | if (typeof p == "undefined") p = d * (.3 * 1.5);
128 | if (!a || a < Math.abs(c)) {
129 | a = c;
130 | s = p / 4;
131 | } else {
132 | s = p / (2 *Math.PI) * Math.asin(c / a);
133 | }
134 | if (t < 1) return -.5 * (a * Math.pow(2, 10* (t -=1 )) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
135 | return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p ) * .5 + c + b;
136 | }
137 | },
138 | Back: {
139 | easeIn: function(t, b, c, d, s) {
140 | if (typeof s == "undefined") s = 1.70158;
141 | return c * (t /= d) * t * ((s + 1) * t - s) + b;
142 | },
143 | easeOut: function(t, b, c, d, s) {
144 | if (typeof s == "undefined") s = 1.70158;
145 | return c * ((t = t/d - 1) * t * ((s + 1) * t + s) + 1) + b;
146 | },
147 | easeInOut: function(t, b, c, d, s) {
148 | if (typeof s == "undefined") s = 1.70158;
149 | if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
150 | return c / 2*((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
151 | }
152 | },
153 | Bounce: {
154 | easeIn: function(t, b, c, d) {
155 | return c - Tween.Bounce.easeOut(d-t, 0, c, d) + b;
156 | },
157 | easeOut: function(t, b, c, d) {
158 | if ((t /= d) < (1 / 2.75)) {
159 | return c * (7.5625 * t * t) + b;
160 | } else if (t < (2 / 2.75)) {
161 | return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
162 | } else if (t < (2.5 / 2.75)) {
163 | return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
164 | } else {
165 | return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
166 | }
167 | },
168 | easeInOut: function(t, b, c, d) {
169 | if (t < d / 2) {
170 | return Tween.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;
171 | } else {
172 | return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
173 | }
174 | }
175 | }
176 | }
177 | Math.tween = Tween;
--------------------------------------------------------------------------------
/static/upload/avatar/1536199860345.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/upload/avatar/1536199860345.png
--------------------------------------------------------------------------------
/static/upload/avatar/1536199928211.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bestRenekton/taoLand/96240939ad44dfce4a8fc2effb5472a50b4fb18c/static/upload/avatar/1536199928211.png
--------------------------------------------------------------------------------
/test/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // The assertion name is the filename.
3 | // Example usage:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // For more information on custom assertions see:
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 |
10 | exports.assertion = function (selector, count) {
11 | this.message = 'Testing if element <' + selector + '> has count: ' + count
12 | this.expected = count
13 | this.pass = function (val) {
14 | return val === this.expected
15 | }
16 | this.value = function (res) {
17 | return res.value
18 | }
19 | this.command = function (cb) {
20 | var self = this
21 | return this.api.execute(function (selector) {
22 | return document.querySelectorAll(selector).length
23 | }, [selector], function (res) {
24 | cb.call(self, res)
25 | })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/test/e2e/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-register')
2 | var config = require('../../config')
3 |
4 | // http://nightwatchjs.org/gettingstarted#settings-file
5 | module.exports = {
6 | src_folders: ['test/e2e/specs'],
7 | output_folder: 'test/e2e/reports',
8 | custom_assertions_path: ['test/e2e/custom-assertions'],
9 |
10 | selenium: {
11 | start_process: true,
12 | server_path: require('selenium-server').path,
13 | host: '127.0.0.1',
14 | port: 4444,
15 | cli_args: {
16 | 'webdriver.chrome.driver': require('chromedriver').path
17 | }
18 | },
19 |
20 | test_settings: {
21 | default: {
22 | selenium_port: 4444,
23 | selenium_host: 'localhost',
24 | silent: true,
25 | globals: {
26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
27 | }
28 | },
29 |
30 | chrome: {
31 | desiredCapabilities: {
32 | browserName: 'chrome',
33 | javascriptEnabled: true,
34 | acceptSslCerts: true
35 | }
36 | },
37 |
38 | firefox: {
39 | desiredCapabilities: {
40 | browserName: 'firefox',
41 | javascriptEnabled: true,
42 | acceptSslCerts: true
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/test/e2e/runner.js:
--------------------------------------------------------------------------------
1 | // 1. start the dev server using production config
2 | process.env.NODE_ENV = 'testing'
3 |
4 | const webpack = require('webpack')
5 | const DevServer = require('webpack-dev-server')
6 |
7 | const webpackConfig = require('../../build/webpack.prod.conf')
8 | const devConfigPromise = require('../../build/webpack.dev.conf')
9 |
10 | let server
11 |
12 | devConfigPromise.then(devConfig => {
13 | const devServerOptions = devConfig.devServer
14 | const compiler = webpack(webpackConfig)
15 | server = new DevServer(compiler, devServerOptions)
16 | const port = devServerOptions.port
17 | const host = devServerOptions.host
18 | return server.listen(port, host)
19 | })
20 | .then(() => {
21 | // 2. run the nightwatch test suite against it
22 | // to run in additional browsers:
23 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
24 | // 2. add it to the --env flag below
25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
26 | // For more information on Nightwatch's config file, see
27 | // http://nightwatchjs.org/guide#settings-file
28 | let opts = process.argv.slice(2)
29 | if (opts.indexOf('--config') === -1) {
30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
31 | }
32 | if (opts.indexOf('--env') === -1) {
33 | opts = opts.concat(['--env', 'chrome'])
34 | }
35 |
36 | const spawn = require('cross-spawn')
37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
38 |
39 | runner.on('exit', function (code) {
40 | server.close()
41 | process.exit(code)
42 | })
43 |
44 | runner.on('error', function (err) {
45 | server.close()
46 | throw err
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/test/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': function (browser) {
6 | // automatically uses dev Server port from /config.index.js
7 | // default: http://localhost:8080
8 | // see nightwatch.conf.js
9 | const devServer = browser.globals.devServerURL
10 |
11 | browser
12 | .url(devServer)
13 | .waitForElementVisible('#app', 5000)
14 | .assert.elementPresent('.hello')
15 | .assert.containsText('h1', 'Welcome to Your Vue.js App')
16 | .assert.elementCount('img', 1)
17 | .end()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/unit/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "jest": true
4 | },
5 | "globals": {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/test/unit/jest.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | rootDir: path.resolve(__dirname, '../../'),
5 | moduleFileExtensions: [
6 | 'js',
7 | 'json',
8 | 'vue'
9 | ],
10 | moduleNameMapper: {
11 | '^@/(.*)$': '/src/$1'
12 | },
13 | transform: {
14 | '^.+\\.js$': '/node_modules/babel-jest',
15 | '.*\\.(vue)$': '/node_modules/vue-jest'
16 | },
17 | testPathIgnorePatterns: [
18 | '/test/e2e'
19 | ],
20 | snapshotSerializers: ['/node_modules/jest-serializer-vue'],
21 | setupFiles: ['/test/unit/setup'],
22 | mapCoverage: true,
23 | coverageDirectory: '/test/unit/coverage',
24 | collectCoverageFrom: [
25 | 'src/**/*.{js,vue}',
26 | '!src/main.js',
27 | '!src/router/index.js',
28 | '!**/node_modules/**'
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/test/unit/setup.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | Vue.config.productionTip = false
4 |
--------------------------------------------------------------------------------
/test/unit/specs/HelloWorld.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import HelloWorld from '@/components/HelloWorld'
3 |
4 | describe('HelloWorld.vue', () => {
5 | it('should render correct contents', () => {
6 | const Constructor = Vue.extend(HelloWorld)
7 | const vm = new Constructor().$mount()
8 | expect(vm.$el.querySelector('.hello h1').textContent)
9 | .toEqual('Welcome to Your Vue.js App')
10 | })
11 | })
12 |
--------------------------------------------------------------------------------