@ -1,12 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
|
||||
}
|
||||
}],
|
||||
"stage-2"
|
||||
],
|
||||
"plugins": ["transform-vue-jsx", "transform-runtime"]
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
@ -1,14 +0,0 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
@ -1,10 +0,0 @@
|
||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||
|
||||
module.exports = {
|
||||
"plugins": {
|
||||
"postcss-import": {},
|
||||
"postcss-url": {},
|
||||
// to edit target browsers: use "browserslist" field in package.json
|
||||
"autoprefixer": {}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
# vue-starter
|
||||
|
||||
> A vuejs starter project integrated with vuex, vue-router, less, iview
|
||||
|
||||
## Build Setup
|
||||
|
||||
``` bash
|
||||
# install dependencies
|
||||
npm install
|
||||
|
||||
# serve with hot reload at localhost:8080
|
||||
npm run dev
|
||||
|
||||
# build for production with minification
|
||||
npm run build
|
||||
|
||||
# build for production and view the bundle analyzer report
|
||||
npm run build --report
|
||||
```
|
||||
|
||||
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
|
@ -1,41 +0,0 @@
|
||||
'use strict'
|
||||
require('./check-versions')()
|
||||
|
||||
process.env.NODE_ENV = 'production'
|
||||
|
||||
const ora = require('ora')
|
||||
const rm = require('rimraf')
|
||||
const path = require('path')
|
||||
const chalk = require('chalk')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const webpackConfig = require('./webpack.prod.conf')
|
||||
|
||||
const spinner = ora('building for production...')
|
||||
spinner.start()
|
||||
|
||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
||||
if (err) throw err
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
spinner.stop()
|
||||
if (err) throw err
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n\n')
|
||||
|
||||
if (stats.hasErrors()) {
|
||||
console.log(chalk.red(' Build failed with errors.\n'))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(chalk.cyan(' Build complete.\n'))
|
||||
console.log(chalk.yellow(
|
||||
' Tip: built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
))
|
||||
})
|
||||
})
|
@ -1,54 +0,0 @@
|
||||
'use strict'
|
||||
const chalk = require('chalk')
|
||||
const semver = require('semver')
|
||||
const packageConfig = require('../package.json')
|
||||
const shell = require('shelljs')
|
||||
|
||||
function exec (cmd) {
|
||||
return require('child_process').execSync(cmd).toString().trim()
|
||||
}
|
||||
|
||||
const versionRequirements = [
|
||||
{
|
||||
name: 'node',
|
||||
currentVersion: semver.clean(process.version),
|
||||
versionRequirement: packageConfig.engines.node
|
||||
}
|
||||
]
|
||||
|
||||
if (shell.which('npm')) {
|
||||
versionRequirements.push({
|
||||
name: 'npm',
|
||||
currentVersion: exec('npm --version'),
|
||||
versionRequirement: packageConfig.engines.npm
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
const warnings = []
|
||||
|
||||
for (let i = 0; i < versionRequirements.length; i++) {
|
||||
const mod = versionRequirements[i]
|
||||
|
||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
||||
warnings.push(mod.name + ': ' +
|
||||
chalk.red(mod.currentVersion) + ' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (warnings.length) {
|
||||
console.log('')
|
||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
||||
console.log()
|
||||
|
||||
for (let i = 0; i < warnings.length; i++) {
|
||||
const warning = warnings[i]
|
||||
console.log(' ' + warning)
|
||||
}
|
||||
|
||||
console.log()
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 6.7 KiB |
@ -1,101 +0,0 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const config = require('../config')
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const packageConfig = require('../package.json')
|
||||
|
||||
exports.assetsPath = function (_path) {
|
||||
const assetsSubDirectory = process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsSubDirectory
|
||||
: config.dev.assetsSubDirectory
|
||||
|
||||
return path.posix.join(assetsSubDirectory, _path)
|
||||
}
|
||||
|
||||
exports.cssLoaders = function (options) {
|
||||
options = options || {}
|
||||
|
||||
const cssLoader = {
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: options.sourceMap
|
||||
}
|
||||
}
|
||||
|
||||
const postcssLoader = {
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
sourceMap: options.sourceMap
|
||||
}
|
||||
}
|
||||
|
||||
// generate loader string to be used with extract text plugin
|
||||
function generateLoaders (loader, loaderOptions) {
|
||||
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
|
||||
|
||||
if (loader) {
|
||||
loaders.push({
|
||||
loader: loader + '-loader',
|
||||
options: Object.assign({}, loaderOptions, {
|
||||
sourceMap: options.sourceMap
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Extract CSS when that option is specified
|
||||
// (which is the case during production build)
|
||||
if (options.extract) {
|
||||
return ExtractTextPlugin.extract({
|
||||
use: loaders,
|
||||
fallback: 'vue-style-loader'
|
||||
})
|
||||
} else {
|
||||
return ['vue-style-loader'].concat(loaders)
|
||||
}
|
||||
}
|
||||
|
||||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
|
||||
return {
|
||||
css: generateLoaders(),
|
||||
postcss: generateLoaders(),
|
||||
less: generateLoaders('less'),
|
||||
sass: generateLoaders('sass', { indentedSyntax: true }),
|
||||
scss: generateLoaders('sass'),
|
||||
stylus: generateLoaders('stylus'),
|
||||
styl: generateLoaders('stylus')
|
||||
}
|
||||
}
|
||||
|
||||
// Generate loaders for standalone style files (outside of .vue)
|
||||
exports.styleLoaders = function (options) {
|
||||
const output = []
|
||||
const loaders = exports.cssLoaders(options)
|
||||
|
||||
for (const extension in loaders) {
|
||||
const loader = loaders[extension]
|
||||
output.push({
|
||||
test: new RegExp('\\.' + extension + '$'),
|
||||
use: loader
|
||||
})
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
exports.createNotifierCallback = () => {
|
||||
const notifier = require('node-notifier')
|
||||
|
||||
return (severity, errors) => {
|
||||
if (severity !== 'error') return
|
||||
|
||||
const error = errors[0]
|
||||
const filename = error.file && error.file.split('!').pop()
|
||||
|
||||
notifier.notify({
|
||||
title: packageConfig.name,
|
||||
message: severity + ': ' + error.name,
|
||||
subtitle: filename || '',
|
||||
icon: path.join(__dirname, 'logo.png')
|
||||
})
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
'use strict'
|
||||
const utils = require('./utils')
|
||||
const config = require('../config')
|
||||
const isProduction = process.env.NODE_ENV === 'production'
|
||||
const sourceMapEnabled = isProduction
|
||||
? config.build.productionSourceMap
|
||||
: config.dev.cssSourceMap
|
||||
|
||||
module.exports = {
|
||||
loaders: utils.cssLoaders({
|
||||
sourceMap: sourceMapEnabled,
|
||||
extract: isProduction
|
||||
}),
|
||||
cssSourceMap: sourceMapEnabled,
|
||||
cacheBusting: config.dev.cacheBusting,
|
||||
transformToRequire: {
|
||||
video: ['src', 'poster'],
|
||||
source: 'src',
|
||||
img: 'src',
|
||||
image: 'xlink:href'
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const utils = require('./utils')
|
||||
const config = require('../config')
|
||||
const vueLoaderConfig = require('./vue-loader.conf')
|
||||
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
context: path.resolve(__dirname, '../'),
|
||||
entry: {
|
||||
app: './src/main.js'
|
||||
},
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: '[name].js',
|
||||
publicPath: process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsPublicPath
|
||||
: config.dev.assetsPublicPath
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.vue', '.json'],
|
||||
alias: {
|
||||
'vue$': 'vue/dist/vue.esm.js',
|
||||
'@': resolve('src'),
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
options: vueLoaderConfig
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('img/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('media/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
loader: "style-loader!css-loader!less-loader",
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
node: {
|
||||
// prevent webpack from injecting useless setImmediate polyfill because Vue
|
||||
// source contains it (although only uses it if it's native).
|
||||
setImmediate: false,
|
||||
// prevent webpack from injecting mocks to Node native modules
|
||||
// that does not make sense for the client
|
||||
dgram: 'empty',
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty',
|
||||
child_process: 'empty'
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
'use strict'
|
||||
const utils = require('./utils')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const merge = require('webpack-merge')
|
||||
const path = require('path')
|
||||
const baseWebpackConfig = require('./webpack.base.conf')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
|
||||
const portfinder = require('portfinder')
|
||||
|
||||
const HOST = process.env.HOST
|
||||
const PORT = process.env.PORT && Number(process.env.PORT)
|
||||
|
||||
const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
|
||||
},
|
||||
// cheap-module-eval-source-map is faster for development
|
||||
devtool: config.dev.devtool,
|
||||
|
||||
// these devServer options should be customized in /config/index.js
|
||||
devServer: {
|
||||
clientLogLevel: 'warning',
|
||||
historyApiFallback: {
|
||||
rewrites: [
|
||||
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
|
||||
],
|
||||
},
|
||||
hot: true,
|
||||
contentBase: false, // since we use CopyWebpackPlugin.
|
||||
compress: true,
|
||||
host: HOST || config.dev.host,
|
||||
port: PORT || config.dev.port,
|
||||
open: config.dev.autoOpenBrowser,
|
||||
overlay: config.dev.errorOverlay
|
||||
? { warnings: false, errors: true }
|
||||
: false,
|
||||
publicPath: config.dev.assetsPublicPath,
|
||||
proxy: config.dev.proxyTable,
|
||||
quiet: true, // necessary for FriendlyErrorsPlugin
|
||||
watchOptions: {
|
||||
poll: config.dev.poll,
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': require('../config/dev.env')
|
||||
}),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
// https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: 'index.html',
|
||||
inject: true
|
||||
}),
|
||||
// copy custom static assets
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.resolve(__dirname, '../static'),
|
||||
to: config.dev.assetsSubDirectory,
|
||||
ignore: ['.*']
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
|
||||
module.exports = new Promise((resolve, reject) => {
|
||||
portfinder.basePort = process.env.PORT || config.dev.port
|
||||
portfinder.getPort((err, port) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
// publish the new Port, necessary for e2e tests
|
||||
process.env.PORT = port
|
||||
// add port to devServer config
|
||||
devWebpackConfig.devServer.port = port
|
||||
|
||||
// Add FriendlyErrorsPlugin
|
||||
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
|
||||
compilationSuccessInfo: {
|
||||
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
|
||||
},
|
||||
onErrors: config.dev.notifyOnErrors
|
||||
? utils.createNotifierCallback()
|
||||
: undefined
|
||||
}))
|
||||
|
||||
resolve(devWebpackConfig)
|
||||
}
|
||||
})
|
||||
})
|
@ -1,145 +0,0 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const utils = require('./utils')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const merge = require('webpack-merge')
|
||||
const baseWebpackConfig = require('./webpack.base.conf')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
|
||||
|
||||
const env = require('../config/prod.env')
|
||||
|
||||
const webpackConfig = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
rules: utils.styleLoaders({
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
extract: true,
|
||||
usePostCSS: true
|
||||
})
|
||||
},
|
||||
devtool: config.build.productionSourceMap ? config.build.devtool : false,
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: utils.assetsPath('js/[name].[chunkhash].js'),
|
||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
|
||||
},
|
||||
plugins: [
|
||||
// http://vuejs.github.io/vue-loader/en/workflow/production.html
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env
|
||||
}),
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
},
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
parallel: true
|
||||
}),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin({
|
||||
filename: utils.assetsPath('css/[name].[contenthash].css'),
|
||||
// Setting the following option to `false` will not extract CSS from codesplit chunks.
|
||||
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
|
||||
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
|
||||
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
|
||||
allChunks: true,
|
||||
}),
|
||||
// Compress extracted CSS. We are using this plugin so that possible
|
||||
// duplicated CSS from different components can be deduped.
|
||||
new OptimizeCSSPlugin({
|
||||
cssProcessorOptions: config.build.productionSourceMap
|
||||
? { safe: true, map: { inline: false } }
|
||||
: { safe: true }
|
||||
}),
|
||||
// generate dist index.html with correct asset hash for caching.
|
||||
// you can customize output by editing /index.html
|
||||
// see https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: config.build.index,
|
||||
template: 'index.html',
|
||||
inject: true,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true
|
||||
// more options:
|
||||
// https://github.com/kangax/html-minifier#options-quick-reference
|
||||
},
|
||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||
chunksSortMode: 'dependency'
|
||||
}),
|
||||
// keep module.id stable when vendor modules does not change
|
||||
new webpack.HashedModuleIdsPlugin(),
|
||||
// enable scope hoisting
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
// split vendor js into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks (module) {
|
||||
// any required modules inside node_modules are extracted to vendor
|
||||
return (
|
||||
module.resource &&
|
||||
/\.js$/.test(module.resource) &&
|
||||
module.resource.indexOf(
|
||||
path.join(__dirname, '../node_modules')
|
||||
) === 0
|
||||
)
|
||||
}
|
||||
}),
|
||||
// extract webpack runtime and module manifest to its own file in order to
|
||||
// prevent vendor hash from being updated whenever app bundle is updated
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'manifest',
|
||||
minChunks: Infinity
|
||||
}),
|
||||
// This instance extracts shared chunks from code splitted chunks and bundles them
|
||||
// in a separate chunk, similar to the vendor chunk
|
||||
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'app',
|
||||
async: 'vendor-async',
|
||||
children: true,
|
||||
minChunks: 3
|
||||
}),
|
||||
|
||||
// copy custom static assets
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.resolve(__dirname, '../static'),
|
||||
to: config.build.assetsSubDirectory,
|
||||
ignore: ['.*']
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
|
||||
if (config.build.productionGzip) {
|
||||
const CompressionWebpackPlugin = require('compression-webpack-plugin')
|
||||
|
||||
webpackConfig.plugins.push(
|
||||
new CompressionWebpackPlugin({
|
||||
asset: '[path].gz[query]',
|
||||
algorithm: 'gzip',
|
||||
test: new RegExp(
|
||||
'\\.(' +
|
||||
config.build.productionGzipExtensions.join('|') +
|
||||
')$'
|
||||
),
|
||||
threshold: 10240,
|
||||
minRatio: 0.8
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (config.build.bundleAnalyzerReport) {
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
||||
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
|
||||
}
|
||||
|
||||
module.exports = webpackConfig
|
@ -1,8 +0,0 @@
|
||||
'use strict'
|
||||
const merge = require('webpack-merge')
|
||||
const prodEnv = require('./prod.env')
|
||||
|
||||
module.exports = merge(prodEnv, {
|
||||
NODE_ENV: '"development"',
|
||||
WEB_ADDR: '"http://localhost:10086"'
|
||||
})
|
@ -1,69 +0,0 @@
|
||||
'use strict'
|
||||
// Template version: 1.3.1
|
||||
// see http://vuejs-templates.github.io/webpack for documentation.
|
||||
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
dev: {
|
||||
|
||||
// Paths
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
proxyTable: {},
|
||||
|
||||
// Various Dev Server settings
|
||||
host: 'localhost', // can be overwritten by process.env.HOST
|
||||
port: 9532, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
||||
autoOpenBrowser: true,
|
||||
errorOverlay: true,
|
||||
notifyOnErrors: true,
|
||||
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
|
||||
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
// https://webpack.js.org/configuration/devtool/#development
|
||||
devtool: 'cheap-module-eval-source-map',
|
||||
|
||||
// If you have problems debugging vue-files in devtools,
|
||||
// set this to false - it *may* help
|
||||
// https://vue-loader.vuejs.org/en/options.html#cachebusting
|
||||
cacheBusting: true,
|
||||
|
||||
cssSourceMap: true
|
||||
},
|
||||
|
||||
build: {
|
||||
// Template for index.html
|
||||
index: path.resolve(__dirname, '../dist/index.html'),
|
||||
|
||||
// Paths
|
||||
assetsRoot: path.resolve(__dirname, '../dist'),
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
productionSourceMap: true,
|
||||
// https://webpack.js.org/configuration/devtool/#production
|
||||
devtool: '#source-map',
|
||||
|
||||
// Gzip off by default as many popular static hosts such as
|
||||
// Surge or Netlify already gzip all static assets for you.
|
||||
// Before setting to `true`, make sure to:
|
||||
// npm install --save-dev compression-webpack-plugin
|
||||
productionGzip: false,
|
||||
productionGzipExtensions: ['js', 'css'],
|
||||
|
||||
// Run the build command with an extra argument to
|
||||
// View the bundle analyzer report after build finishes:
|
||||
// `npm run build --report`
|
||||
// Set to `true` or `false` to always turn it on or off
|
||||
bundleAnalyzerReport: process.env.npm_config_report
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
'use strict'
|
||||
module.exports = {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>im.dev</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
@ -1,72 +0,0 @@
|
||||
{
|
||||
"name": "mafanr",
|
||||
"version": "1.0.0",
|
||||
"description": "A Vue.js project",
|
||||
"author": "sunface <cto@188.com>",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
||||
"start": "npm run dev",
|
||||
"build": "node build/build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "0.17.1",
|
||||
"element-ui": "^2.11.1",
|
||||
"js-cookie": "2.2.0",
|
||||
"mavon-editor": "^2.7.5",
|
||||
"vue": "^2.6.10",
|
||||
"vue-i18n": "^8.11.2",
|
||||
"vue-router": "^3.0.3",
|
||||
"vuex": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.1.2",
|
||||
"babel-core": "^6.22.1",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"babel-plugin-transform-runtime": "^6.22.0",
|
||||
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
||||
"babel-preset-env": "^1.3.2",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"chalk": "^2.0.1",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"css-loader": "^0.23.1",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^1.1.4",
|
||||
"friendly-errors-webpack-plugin": "^1.6.1",
|
||||
"html-loader": "^0.3.0",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"less": "^2.7.1",
|
||||
"less-loader": "^2.2.3",
|
||||
"node-notifier": "^5.1.2",
|
||||
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
||||
"ora": "^1.2.0",
|
||||
"portfinder": "^1.0.13",
|
||||
"postcss-import": "^11.0.0",
|
||||
"postcss-loader": "^2.0.8",
|
||||
"postcss-url": "^7.2.1",
|
||||
"rimraf": "^2.6.0",
|
||||
"semver": "^5.3.0",
|
||||
"shelljs": "^0.7.6",
|
||||
"style-loader": "^0.13.1",
|
||||
"uglifyjs-webpack-plugin": "^1.1.1",
|
||||
"url-loader": "^0.5.8",
|
||||
"vue-loader": "^13.3.0",
|
||||
"vue-style-loader": "^3.0.1",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
"webpack": "^3.6.0",
|
||||
"webpack-bundle-analyzer": "^2.9.0",
|
||||
"webpack-dev-server": "^2.9.1",
|
||||
"webpack-merge": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<style lang="less" scoped>
|
||||
</style>
|
Before Width: | Height: | Size: 160 KiB |
Before Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 4.7 KiB |
@ -1,37 +0,0 @@
|
||||
@font-face {font-family: "iconfont";
|
||||
src: url('iconfont.eot?t=1568170482672'); /* IE9 */
|
||||
src: url('iconfont.eot?t=1568170482672#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAPEAAsAAAAACEgAAAN1AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDOAqDQIMIATYCJAMYCw4ABCAFhG0HZBs6BxEVnHnIfh7GtojtKjpzws2LWP1NWda478HzlIe9yZ+kKYRT11ZW9lFAunYSIKBu37nvH9BA+KhzQ/ntkUc7TIGy16YH1Uf/w/1Ml+L57NtcolqjEgc4HtC0Isl2gHgK4tl08D8Bu6EAP5Jkp8pXrF4fG40+SAGqe5dObbATSnRFpMJGYRXM1JFqFia2Mdk4D8z0/l69IW82GJiCvlftjhXaU9qNcQuK4zk0F4exw+kBfh4IkB1oUN0LjR2RwJmd4Kf6a4oC29AbMJQzv1vQ8xhcXvZWGJXBAYBgbOMfzwRloYcHAFAdLhPcGAuBgJsXgQFuPgQK3PwINLgFszABsAZMt4EBwEGKzxCr49cpvwD9gsiYOrDHrbtt6diJJw/a3bzZ8NatRjduNLh+3afHaeDVx1vaLFi6cX1kg/mL1m2IGiZrblYMOn49xVh9owLz10c3Cjx1q5EfteQBpH39G8zfGK38OX469e12u/HhGxVCY+eU7bpjSq97zY7drBhy/HqZLtun/hrVemOjWmXN/6P0kT+nFWOFO/7bJCtLtss2h7+No0d00OC7vdQsOXxYbN5Mjg4GQwNvFpKnFVmSrdbhIaVruq3I3+HSZuXKtUvXpkIz8O8eUGTB+mHDkoTD+x1HObrXVqWdQt4f0bqgSED3ejb2HL8QaPik59muFb5mV5G+NP5Fc6oXzd7VHQDPkSvigHdIBkhpL3SA8cYTf/2qh9Hhcr7/rYKLf7P9NQB3Voz5jB5ej3bEgU/Dasz6hnLtVKByNY6usrTCstAOnyZ0MDWyRQ5iNwA/QwNfzwthHg4lipyI6ZhtIiMw8CERBJsMtMZnBxN/8oOFTSnwI5tK8/0J1xdBaV8g03gCihA7wSCIQyCEuIDW+AdgEuUdWIQkwCt8F75i6TFdlIu4MO6w/oPeKAhTw4Uf+Y4yuyXGOR7hG2PSFhjaPu15w4BxiDHpR47MAkQkD69kP3SO4IhkcONWMR/nrhNFX2o38qfCkwgtGNqB1T+gbUggnNKsyPz+HZIyZxErCqrU31CU6MrBoNU3QL8JQ6OCS7kn+SGNGBOAEBEPvBJ/5DikCY/ibgbasJbqYD+cdUYx0VTYTi/2d7kM8KOfY2UoUVqZylI+XB92uu1HOWWqdvFgj4FTsziuu+olMOUpqSXIMuH408vpBAAAAA==') format('woff2'),
|
||||
url('iconfont.woff?t=1568170482672') format('woff'),
|
||||
url('iconfont.ttf?t=1568170482672') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
|
||||
url('iconfont.svg?t=1568170482672#iconfont') format('svg'); /* iOS 4.1- */
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-undo:before {
|
||||
content: "\e633";
|
||||
}
|
||||
|
||||
.icon-sousuo:before {
|
||||
content: "\e632";
|
||||
}
|
||||
|
||||
.icon-comments-alt:before {
|
||||
content: "\e618";
|
||||
}
|
||||
|
||||
.icon-jiantou_shang:before {
|
||||
content: "\e634";
|
||||
}
|
||||
|
||||
.icon-jiantou_xia:before {
|
||||
content: "\e636";
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 203 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.1 KiB |
@ -1,12 +0,0 @@
|
||||
export default {
|
||||
nav: {
|
||||
signIn : 'Sign in',
|
||||
signInTitle: "Welcome to I'm Dev",
|
||||
whySignIn: 'Sign in to get personalized story recommendations, follow authors and topics you love, and interact with stories.',
|
||||
signInFooter: "I'm Dev is 100% open-source, if you are intrest in building developer commnity, please join us in github.",
|
||||
navSearchHolder: 'Search in Dev',
|
||||
setLang: 'Lang',
|
||||
setTheme: 'Theme',
|
||||
readingLang: 'Reading Lang',
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import VueI18n from 'vue-i18n'
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import eleEN from 'element-ui/lib/locale/lang/en'
|
||||
import eleZh from 'element-ui/lib/locale/lang/zh-CN'
|
||||
|
||||
import enLocale from './en'
|
||||
import zhLocale from './zh'
|
||||
|
||||
Vue.use(VueI18n)
|
||||
Vue.locale = () => {}
|
||||
|
||||
const messages = {
|
||||
en: {
|
||||
...enLocale,
|
||||
...eleEN
|
||||
},
|
||||
zh: {
|
||||
...zhLocale,
|
||||
...eleZh
|
||||
}
|
||||
}
|
||||
|
||||
const i18n = new VueI18n({
|
||||
// set locale
|
||||
// options: en or zh
|
||||
locale: Cookies.get('imdev-lang') || 'en',
|
||||
// set locale messages
|
||||
messages
|
||||
})
|
||||
|
||||
export default i18n
|
@ -1,12 +0,0 @@
|
||||
export default {
|
||||
nav: {
|
||||
signIn : '登录',
|
||||
signInTitle: "欢迎来到I'm Dev开发者社区",
|
||||
whySignIn: '登录后你可以创建自己的资料、发表文章,接收个性化推荐收藏喜欢的文章、与其它成员互动等',
|
||||
signInFooter: "I'm Dev的源码是100%开源的,如果你对参与创建个性化社区充满兴趣,欢迎加入我们的组织",
|
||||
navSearchHolder: 'Search in Dev',
|
||||
setLang: '语言设置',
|
||||
setTheme: '主题设置',
|
||||
readingLang: '阅读语言偏好'
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
import Nav from '@/views/nav'
|
||||
Vue.use(Router)
|
||||
|
||||
|
||||
|
||||
const router = new Router({
|
||||
mode: 'history',
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
component: Nav,
|
||||
children: [
|
||||
{ path: '/', meta: {'title':'im.dev'}, component: () => import('@/views/home')},
|
||||
{ path: '/dev/article/new', meta: {'title':'Post - im.dev'},component: () => import('@/views/article/edit')},
|
||||
{
|
||||
path: '/dev/setting',
|
||||
component: () => import('@/views/setting/nav'),
|
||||
redirect: '/dev/setting/account',
|
||||
meta: '综合监控',
|
||||
children: [
|
||||
{ path: '/dev/setting/account',meta: {'title':'Settings - im.dev'}, component: () => import('@/views/setting/account')},
|
||||
{ path: '/dev/setting/profile',meta: {'title':'Settings - im.dev'}, component: () => import('@/views/setting/profile')},
|
||||
]
|
||||
},
|
||||
{ path: '/:uname/:arID', meta: {'title':'Article - im.dev',},component: () => import('@/views/article/detail')},
|
||||
{ path: '/:uname/:arID/edit', meta: {'title':'Post - im.dev'},component: () => import('@/views/article/edit')},
|
||||
]
|
||||
},
|
||||
// { path: '/404', component: () => import('@/views/errorPage/page404')},
|
||||
// { path: '*', redirect: '/404'}
|
||||
],
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
if (savedPosition) {
|
||||
resolve(savedPosition)
|
||||
} else {
|
||||
resolve( { x: 0, y: 0 })
|
||||
}
|
||||
}, 500)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (to.meta.title) {
|
||||
document.title = to.meta.title
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
export default router
|
@ -1,7 +0,0 @@
|
||||
/* eslint-disable */
|
||||
const getters = {
|
||||
//misc
|
||||
service: state => state.misc.service
|
||||
}
|
||||
export default getters
|
||||
|
@ -1,20 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import misc from './modules/misc'
|
||||
import user from './modules/user'
|
||||
import post from './modules/post'
|
||||
import getters from './getters'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
misc,
|
||||
user,
|
||||
post
|
||||
},
|
||||
getters
|
||||
})
|
||||
|
||||
export default store
|
||||
|
@ -1,63 +0,0 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
const misc = {
|
||||
state: {
|
||||
theme: Cookies.get('imdev-theme') || 'light',
|
||||
lang: Cookies.get('imdev-lang') || 'en',
|
||||
readingLang: getReadingLang(self.lang),
|
||||
needSignin: 0,
|
||||
navFixed : true
|
||||
},
|
||||
mutations: {
|
||||
SET_THEME: (state, theme) => {
|
||||
state.theme = theme
|
||||
Cookies.set('imdev-theme', theme)
|
||||
},
|
||||
SET_LANG: (state, lang) => {
|
||||
state.lang = lang
|
||||
Cookies.set('imdev-lang', lang)
|
||||
},
|
||||
SET_READING_LANG: (state, lang) => {
|
||||
if (lang.length == 0) {
|
||||
Cookies.remove('imdev-reading-lang')
|
||||
} else {
|
||||
state.readingLang = lang
|
||||
Cookies.set('imdev-reading-lang', JSON.stringify(lang))
|
||||
}
|
||||
},
|
||||
SET_NEEDSIGNIN: (state, _) => {
|
||||
state.needSignin++
|
||||
},
|
||||
SET_NAVFIXED: (state, val) => {
|
||||
state.navFixed = val
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setTheme({ commit }, theme) {
|
||||
commit('SET_THEME', theme)
|
||||
},
|
||||
setLang({ commit }, val) {
|
||||
commit('SET_LANG', val)
|
||||
},
|
||||
setReadingLang({ commit }, val) {
|
||||
commit('SET_READING_LANG', val)
|
||||
},
|
||||
setNeedSignin({ commit }, val) {
|
||||
commit('SET_NEEDSIGNIN', val)
|
||||
},
|
||||
setNavFixed({ commit }, val) {
|
||||
commit('SET_NAVFIXED', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getReadingLang() {
|
||||
var lang = Cookies.get('imdev-lang') || 'en'
|
||||
var c = Cookies.get('imdev-reading-lang')
|
||||
if (c == undefined) {
|
||||
return [lang]
|
||||
} else {
|
||||
return JSON.parse(c)
|
||||
}
|
||||
}
|
||||
export default misc
|
@ -1,19 +0,0 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
const post = {
|
||||
state: {
|
||||
contentToBottm: 0
|
||||
},
|
||||
mutations: {
|
||||
SET_ContentToBottm: (state, _) => {
|
||||
state.contentToBottm++
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setContentToBottm({ commit }, val) {
|
||||
commit('SET_ContentToBottm', val)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default post
|
@ -1,81 +0,0 @@
|
||||
// overide global focus style
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
margin-block-start: .4em;
|
||||
margin-block-end: .4em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size:19px;
|
||||
font-weight:500;
|
||||
}
|
||||
h4 {
|
||||
font-size:17px;
|
||||
font-weight:500;
|
||||
margin-block-start: .5em;
|
||||
margin-block-end: .5em;
|
||||
}
|
||||
|
||||
:focus {
|
||||
outline-color: transparent;
|
||||
outline-width: 0;
|
||||
outline-style: none;
|
||||
}
|
||||
input::-webkit-input-placeholder {
|
||||
color: #aab2bd;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 2px !important;
|
||||
height: 2px;
|
||||
background-color: #e5e5e5 !important;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #b7b7b7 !important;
|
||||
border-radius: 3px !important;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 0px #808080 inset !important;
|
||||
}
|
||||
|
||||
.no-border {
|
||||
input {
|
||||
border: none;
|
||||
}
|
||||
button {
|
||||
border:none;
|
||||
}
|
||||
}
|
||||
|
||||
.image-modal {
|
||||
.el-dialog {
|
||||
box-shadow: none !important;
|
||||
position: absolute;
|
||||
top: 45%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
cursor: zoom-out;
|
||||
}
|
||||
.el-dialog__header {
|
||||
display: none;
|
||||
}
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.el-message.el-message--error.network-error {
|
||||
top: 20px !important;
|
||||
}
|
||||
|
||||
|
||||
.el-message {
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
.el-divider {
|
||||
margin: 13px 0;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
@import './var.less';
|
||||
|
||||
a {
|
||||
color: @main-color;
|
||||
}
|
||||
|
||||
.el-button.el-button--info {
|
||||
background-color: #f5f6f7;
|
||||
color: @grey-color;
|
||||
}
|
||||
|
||||
.el-dialog__wrapper.white-bg-modal {
|
||||
background-color: rgba(255,255,255,.95);
|
||||
}
|
||||
|
@ -1,631 +0,0 @@
|
||||
@import './var.less';
|
||||
.meta-word {
|
||||
color:@grey-color;
|
||||
}
|
||||
.bold-meta-word {
|
||||
color:@light-grey-color;
|
||||
font-weight:700;
|
||||
}
|
||||
.border-bottom {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.color-regular {
|
||||
color: @regular-color;
|
||||
}
|
||||
|
||||
.global-nav {
|
||||
.write-post {
|
||||
text-decoration:none;color:black;background:#66e2d5;padding:2px 12px;border:2px solid #0a0a0a;border-radius:3px;font-weight:bold;font-size:14px
|
||||
}
|
||||
.sign-in-modal {
|
||||
.el-dialog__header {
|
||||
display: none;
|
||||
}
|
||||
.el-dialog__body {
|
||||
padding: 0 0;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.sign-in-panel {
|
||||
height: 100%;
|
||||
background: url(../../assets/login.png) no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
}
|
||||
.user-panel {
|
||||
div {
|
||||
cursor: pointer;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: all 0.6s;
|
||||
}
|
||||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||
// opacity: 0;
|
||||
transform: translateY(-50px);
|
||||
}
|
||||
|
||||
.fade-leave-active,
|
||||
.fade-enter-active {
|
||||
transition: all 0.4s;
|
||||
}
|
||||
.nav {
|
||||
top: 0;
|
||||
width: 100%;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
position: fixed;
|
||||
|
||||
// box-shadow: rgba(0, 0, 0, 0.0470588) 0px 4px 12px 0px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.nav.toTop {
|
||||
position: fixed;
|
||||
// box-shadow: rgba(0, 0, 0, 0.0470588) 0px 4px 12px 0px;
|
||||
border-bottom: 1px solid #eee;
|
||||
background-color: white;
|
||||
z-index: 999;
|
||||
// transition:transform 300ms ease;
|
||||
// transform: translateY(100px)
|
||||
}
|
||||
.nav.inTop {
|
||||
// box-shadow: rgba(0, 0, 0, 0.0470588) 0px 4px 12px 0px;;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.article-detail {
|
||||
.discuss {
|
||||
background-color: #fafafa
|
||||
}
|
||||
.squares {
|
||||
.square {
|
||||
text-align: center;
|
||||
font-size: 25px;
|
||||
a {
|
||||
color: rgba(0,0,0,.8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.clap {
|
||||
position: relative;
|
||||
outline: 1px solid transparent;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #bdc3c7;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: none;
|
||||
}
|
||||
.clap:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
}
|
||||
.clap:hover {
|
||||
cursor: pointer;
|
||||
border: 1px solid #333;
|
||||
transition: border-color 0.3s ease-in;
|
||||
}
|
||||
.clap:hover:after {
|
||||
animation: shockwave 1s ease-in infinite;
|
||||
}
|
||||
.clap svg {
|
||||
width: 20px;
|
||||
fill: none;
|
||||
stroke: #333;
|
||||
stroke-width: 1px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.clap.liked {
|
||||
border: 1px solid #333;
|
||||
}
|
||||
.clap.liked svg {
|
||||
stroke: #333;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
.clap svg.checked {
|
||||
fill: #333;
|
||||
stroke: #fff;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
@keyframes shockwave {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
box-shadow: 0 0 2px #333;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 0;
|
||||
box-shadow: 0 0 50px #145b32, inset 0 0 10px #333
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.article-edit {
|
||||
.render {
|
||||
border:1px solid #eee;border-bottom:none;border-right:none;
|
||||
}
|
||||
.tags {
|
||||
.el-input.el-input--suffix input{
|
||||
background-color: #f5f6f7;
|
||||
border-radius: 100px
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.component-render {
|
||||
.content p {
|
||||
margin: 0 0 8px
|
||||
}
|
||||
.content blockquote h1:last-child,
|
||||
.content blockquote h2:last-child,
|
||||
.content blockquote h3:last-child,
|
||||
.content blockquote h4:last-child,
|
||||
.content blockquote h5:last-child,
|
||||
.content blockquote h6:last-child,
|
||||
.content blockquote li:last-child,
|
||||
.content blockquote ol:last-child,
|
||||
.content blockquote p:last-child,
|
||||
.content blockquote ul:last-child {
|
||||
margin-bottom: 0
|
||||
}
|
||||
|
||||
.content .video-package .video-description p {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.content li p {
|
||||
overflow: visible
|
||||
}
|
||||
|
||||
.content a {
|
||||
color: rgba(0, 0, 0, .84);
|
||||
text-decoration: none;
|
||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, .68) 50%, rgba(0, 0, 0, 0) 50%);
|
||||
background-repeat: repeat-x;
|
||||
background-size: 2px .2em;
|
||||
background-position: 0 1.07em
|
||||
}
|
||||
|
||||
|
||||
/* .content a:hover {
|
||||
color: #3194d0;
|
||||
text-decoration: underline
|
||||
} */
|
||||
|
||||
|
||||
/* .content a.active,
|
||||
.content a:active,
|
||||
.content a:focus {
|
||||
color: #3194d0
|
||||
} */
|
||||
|
||||
.content a.disabled,
|
||||
.content a.disabled.active,
|
||||
.content a.disabled:active,
|
||||
.content a.disabled:focus,
|
||||
.content a.disabled:hover,
|
||||
.content a[disabled],
|
||||
.content a[disabled].active,
|
||||
.content a[disabled]:active,
|
||||
.content a[disabled]:focus,
|
||||
.content a[disabled]:hover {
|
||||
cursor: not-allowed;
|
||||
color: #f5f5f5
|
||||
}
|
||||
|
||||
.content ol,
|
||||
.content p,
|
||||
.content ul {
|
||||
word-break: break-word!important;
|
||||
word-break: break-all
|
||||
}
|
||||
|
||||
.content hr {
|
||||
margin: 0 0 20px;
|
||||
border-top: 1px solid #ddd
|
||||
}
|
||||
|
||||
|
||||
|
||||
.content h1 {
|
||||
font-size: 26px
|
||||
}
|
||||
|
||||
.content h2 {
|
||||
font-size: 24px
|
||||
}
|
||||
|
||||
.content h3 {
|
||||
font-size: 22px
|
||||
}
|
||||
|
||||
.content h4 {
|
||||
font-size: 20px
|
||||
}
|
||||
|
||||
.content h5 {
|
||||
font-size: 18px
|
||||
}
|
||||
|
||||
.content h6 {
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
.content img {
|
||||
max-width: 100%
|
||||
}
|
||||
|
||||
.content blockquote {
|
||||
font-style: italic;
|
||||
font-size: 18px !important;
|
||||
color: rgba(0, 0, 0, .68);
|
||||
padding-left: 25px;
|
||||
padding-top:4px;
|
||||
padding-bottom: 4px;
|
||||
box-shadow:rgba(0, 0, 0, 0.843137) 3px 0px 0px 0px inset;
|
||||
margin-inline-start: 0px !important;
|
||||
margin-inline-end: 0px !important;
|
||||
margin-left:-20px !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.content ol .image-package,
|
||||
.content ul .image-package {
|
||||
width: auto!important;
|
||||
margin-left: 0!important
|
||||
}
|
||||
|
||||
.content code {
|
||||
background: rgba(0, 0, 0, .05);
|
||||
padding: 3px 4px;
|
||||
margin: 0 2px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.content pre {
|
||||
font-size: 14px;
|
||||
word-wrap: normal;
|
||||
word-break: break-word!important;
|
||||
word-break: break-all;
|
||||
white-space: pre;
|
||||
overflow: auto;
|
||||
border-radius: 0;
|
||||
/* border: .3px solid #ddd;*/
|
||||
page-break-inside: avoid;
|
||||
display: block;
|
||||
/* line-height: 1.42857; */
|
||||
color: #333;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 4px;
|
||||
line-height: 27px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.content pre code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
/* white-space: pre */
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
white-space: pre-wrap;
|
||||
background-color: transparent;
|
||||
border-radius: 0
|
||||
}
|
||||
|
||||
.content table {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
border: 0px solid #ddd;
|
||||
border-collapse: collapse;
|
||||
border-left: none;
|
||||
word-break: normal;
|
||||
display: table;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.content table tr:nth-of-type(2n) {
|
||||
background-color: rgba(243, 243, 243, 0.3)
|
||||
}
|
||||
|
||||
.content table thead th {
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
color: rgba(0, 0, 0, .64);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.content table tr {
|
||||
border-top: .3px solid #ddd;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.content table thead tr {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.content table td,
|
||||
.content table th {
|
||||
padding: 12px 8px;
|
||||
border: 0px solid #ddd;
|
||||
line-height: 20px;
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
.content table th {
|
||||
font-weight: 500
|
||||
}
|
||||
|
||||
.content table .image-package {
|
||||
width: auto;
|
||||
margin-left: 0
|
||||
}
|
||||
|
||||
.content .image-package .image-container {
|
||||
z-index: 100;
|
||||
position: relative;
|
||||
background-color: #eee;
|
||||
transition: background-color .1s linear;
|
||||
margin: 0 auto
|
||||
}
|
||||
|
||||
.content .image-package .image-container .image-container-fill {
|
||||
z-index: 50
|
||||
}
|
||||
|
||||
.content .image-package .image-container .image-view {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.content .image-package .image-container .image-view img.image-loading {
|
||||
will-change: filter, opacity;
|
||||
-webkit-filter: blur(4px);
|
||||
filter: blur(4px);
|
||||
opacity: .3
|
||||
}
|
||||
|
||||
.content .image-package .image-container .image-view img {
|
||||
transition: all .15s linear;
|
||||
z-index: 100;
|
||||
will-change: filter, opacity;
|
||||
-webkit-filter: blur(0);
|
||||
filter: blur(0);
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
.content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
vertical-align: middle;
|
||||
border: 0;
|
||||
cursor: -webkit-zoom-in;
|
||||
transition: all .25s ease-in-out
|
||||
}
|
||||
|
||||
|
||||
|
||||
.content .image-package .image-caption:empty {
|
||||
display: none
|
||||
}
|
||||
|
||||
.content .video-package {
|
||||
position: relative;
|
||||
margin: -20px auto 20px;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.content .video-package .video-placeholder-area {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
height: 110px;
|
||||
padding: 10px;
|
||||
padding-left: 120px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #d9d9d9;
|
||||
background-color: hsla(0, 0%, 71%, .1);
|
||||
text-align: left;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.content .video-package .video-placeholder-area:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
display: block;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
background-image: url(//cdn2.jianshu.io/assets/common/play-btn-c4bc06b9dfe063495b6b8277b14bc5c3.png);
|
||||
background-position: 30px;
|
||||
background-size: 50px;
|
||||
background-repeat: no-repeat;
|
||||
transition: all .1s linear
|
||||
}
|
||||
|
||||
.content .video-package .video-placeholder-area:hover:after {
|
||||
background-color: transparent
|
||||
}
|
||||
|
||||
.content .video-package .video-placeholder-area .video-cover {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
display: block;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
opacity: .8;
|
||||
transition: opacity .1s linear
|
||||
}
|
||||
|
||||
.content .video-package .video-description {
|
||||
min-width: 20%;
|
||||
min-height: 22px;
|
||||
display: none;
|
||||
padding: 10px;
|
||||
margin: 0 auto;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
line-height: 1.7
|
||||
}
|
||||
|
||||
.content .video-package .video-description:empty {
|
||||
display: none
|
||||
}
|
||||
|
||||
.content .video-package .video-close-button,
|
||||
.content .video-package .video-provider-button {
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
line-height: 14px;
|
||||
cursor: pointer;
|
||||
transition: opacity .1s linear
|
||||
}
|
||||
|
||||
.content .video-package .video-close-button i,
|
||||
.content .video-package .video-provider-button i {
|
||||
position: relative;
|
||||
top: 1px
|
||||
}
|
||||
|
||||
.content .video-package .video-provider-button {
|
||||
float: right
|
||||
}
|
||||
|
||||
.content .hljs {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.content .hljs-center {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.content .hljs-right {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.content .hljs-left {
|
||||
text-align: left
|
||||
}
|
||||
}
|
||||
|
||||
.component-editor {
|
||||
.v-note-wrapper {
|
||||
z-index: 10 !important;
|
||||
}
|
||||
|
||||
.v-note-wrapper .v-note-panel {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.v-note-wrapper .v-note-op .v-right-item {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.setting-nav {
|
||||
.header {
|
||||
|
||||
}
|
||||
.item {
|
||||
padding: 15px 12px 8px;
|
||||
}
|
||||
.item.selected {
|
||||
border-bottom: solid 3px #cfd7ff;
|
||||
}
|
||||
}
|
||||
|
||||
.discuss {
|
||||
.write-comment {
|
||||
.header-buttons {
|
||||
margin-top:-190px
|
||||
}
|
||||
}
|
||||
.comments {
|
||||
padding-bottom:30px
|
||||
}
|
||||
.no-comments {
|
||||
.iconfont {
|
||||
color:rgba(0, 121, 211, 0.4);font-size: 30px
|
||||
}
|
||||
}
|
||||
.sorter {
|
||||
color:@grey-color;
|
||||
|
||||
}
|
||||
.comments {
|
||||
background:white;
|
||||
padding:5px 25px;
|
||||
margin-top:0px;
|
||||
.comment {
|
||||
i.vote-highlighted {
|
||||
color: rgb(255, 69, 0);
|
||||
}
|
||||
.upvote {
|
||||
position:absolute;
|
||||
margin-left:-21px;
|
||||
margin-top:-2px;
|
||||
color: @light-grey-color;
|
||||
font-size:10px
|
||||
}
|
||||
.downvote {
|
||||
position:absolute;
|
||||
margin-left:-21px;
|
||||
margin-top:9px;
|
||||
color:@light-grey-color;
|
||||
font-size:10px
|
||||
}
|
||||
.header {
|
||||
color:rgb(124,124,124);
|
||||
.uname {
|
||||
color:rgb(0, 121, 211);
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
color:@light-grey-color;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.v-note-wrapper {
|
||||
min-height: 150px !important;
|
||||
.v-note-op.shadow {
|
||||
box-shadow: none;
|
||||
border-bottom: 1px solid #efefef
|
||||
}
|
||||
textarea {
|
||||
font-size:13px !important;
|
||||
}
|
||||
}
|
||||
.reply-comment {
|
||||
.v-note-wrapper {
|
||||
border:1px solid #eee
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
@grey-color: rgba(0,0,0,.54);
|
||||
@light-grey-color: rgb(135, 138, 140);
|
||||
|
||||
@main-color: #303133;
|
||||
@regular-color: #606266;
|
@ -1,75 +0,0 @@
|
||||
/* ----------------------------margin------------------------ */
|
||||
.margin-0-auto { margin: 0 auto}
|
||||
|
||||
.margin-left-5 {margin-left: 5px};.margin-left-10 {margin-left: 10px};.margin-left-15 {margin-left: 15px};.margin-left-20 {margin-left: 20px};.margin-left-30 {margin-left: 30px};.margin-left-40 {margin-left: 40px};.margin-left-50 {margin-left: 50px};.margin-left-60 {margin-left: 60px};
|
||||
.margin-left--20 {margin-left: -20px};
|
||||
|
||||
.margin-right-5 {margin-right: 5px};.margin-right-10 {margin-right: 10px};.margin-right-15 {margin-right: 15px};.margin-right-20 {margin-right: 20px};.margin-right-30 {margin-right: 30px};.margin-right-40 {margin-right: 40px};
|
||||
|
||||
.margin-top-2 {margin-top: 2px};.margin-top-5 {margin-top: 5px};.margin-top-8 {margin-top: 8px};.margin-top-10 {margin-top: 10px};.margin-top-15 {margin-top: 15px};.margin-top-20 {margin-top: 20px};.margin-top-25 {margin-top: 25px};.margin-top-30 {margin-top: 30px};.margin-top-40 {margin-top: 40px};.margin-top-60 {margin-top: 60px};.margin-top-80 {margin-top: 80px};.margin-top-100 {margin-top: 100px};
|
||||
.margin-top--30 {margin-top: -30px};.margin-top--35 {margin-top: -35px};.margin-top--40 {margin-top: -40px};.margin-top--50 {margin-top: -50px};
|
||||
|
||||
.margin-bottom-5 {margin-bottom: 5px};.margin-bottom-10 {margin-bottom: 10px};.margin-bottom-15 {margin-bottom: 15px};.margin-bottom-20 { margin-bottom: 20px}.margin-bottom-30 {margin-bottom: 30px };.margin-bottom-40 {margin-bottom: 40px };.margin-bottom-50 {margin-bottom: 50px };
|
||||
|
||||
/* ----------------------------padding------------------------ */
|
||||
.padding-5 {padding: 5px 5px};.padding-10 { padding: 10px 10px};.padding-20 {padding: 20px 20px};
|
||||
|
||||
.padding-left-5 {padding-left: 5px};.padding-left-8 {padding-left: 8px};.padding-left-10 {padding-left: 10px};.padding-left-15 {padding-left: 15px};.padding-left-20 {padding-left: 20px};
|
||||
|
||||
.padding-right-5 {padding-right: 5px}.padding-right-10 {padding-right: 10px};.padding-right-15 {padding-right: 15px};.padding-right-20 {padding-right: 20px};
|
||||
|
||||
.padding-top-5 {padding-top: 5px};.padding-top-10 {padding-top: 10px};.padding-top-15 {padding-top: 15px};.padding-top-20 {padding-top: 20px};.padding-top-40 {padding-top: 40px};.padding-top-50 {padding-top: 650px};.padding-top-55 {padding-top: 55px};.padding-top-60 {padding-top: 60px};
|
||||
|
||||
.padding-bottom-5 { padding-bottom: 5px};.padding-bottom-10 {padding-bottom: 10px};.padding-bottom-15 {padding-bottom: 15px};.padding-bottom-20 {padding-bottom: 20px};.padding-bottom-30 {padding-bottom: 30px};.padding-bottom-40 {padding-bottom: 40px};
|
||||
|
||||
/* ----------------------------height/width------------------------ */
|
||||
.height-40{height:40px};.height-45{height:45px};.height-50{height:50px};.height-100{height:100px};.height-150{height:150px};.height-200{height:200px};
|
||||
|
||||
.width-40{width:40px};.width-50{width:50px};.width-100{width:100px};.width-150{width:150px};.width-200{width:200px};.width-300{width:300px};
|
||||
|
||||
.width-100p {width: 100%};
|
||||
|
||||
.max-width-280 {width: 280px};.max-width-300 {width: 300px}
|
||||
|
||||
/* ----------------------------font------------------------ */
|
||||
.font-size-12 {font-size:12px;};.font-size-13 {font-size:13px;};.font-size-14 {font-size:14px;};.font-size-15 {font-size:15px;};.font-size-16 {font-size:16px;};.font-size-18 {font-size:18px;};.font-size-20 {font-size:20px;};.font-size-22 {font-size:22px;};.font-size-24 {font-size:24px;};
|
||||
|
||||
.font-weight-500 {font-weight: 500;};.font-weight-bold {font-weight: bold;}
|
||||
|
||||
/* ----------------------------position------------------------ */
|
||||
.position-fixed {position: fixed};.position-absolute {position: absolute};.position-relative{position: relative};
|
||||
|
||||
/* ----------------------------z-index------------------------ */
|
||||
.z-index-1 {z-index: 1};.z-index-100 {z-index: 100};.z-index-1000 {z-index: 1000};
|
||||
|
||||
/* ----------------------------border------------------------ */
|
||||
.border-none {border:noen};.border-top-none{border-top: none};.border-bottom-none{border-bottom: none};.border-left-none{border-left: none};.border-right-none{border-right: none};
|
||||
|
||||
.border-radius-3{border-radius: 3px};.border-radius-100{border-radius: 100px};
|
||||
|
||||
// 鼠标悬浮
|
||||
.cursor-pointer:hover {
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right
|
||||
}
|
||||
|
||||
.text-align-center {
|
||||
text-align:center
|
||||
}
|
||||
.vertical-align-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display-inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.overflow-y-auto{
|
||||
overflow-y: auto
|
||||
}
|
||||
|
||||
.text-decoration-none {
|
||||
text-decoration: none;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
const TokenKey = 'MF-Token'
|
||||
|
||||
export function getToken() {
|
||||
return Cookies.get(TokenKey)
|
||||
}
|
||||
|
||||
export function setToken(token) {
|
||||
return Cookies.set(TokenKey, token)
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
return Cookies.remove(TokenKey)
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
const langOptions = [
|
||||
{label:'English',value:'en'},
|
||||
{label:"Chinese",value:'zh'}
|
||||
]
|
||||
|
||||
export default langOptions;
|
@ -1,63 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// 该模块用来请求API网关
|
||||
import axios from 'axios'
|
||||
import { Message } from 'element-ui'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import store from '@/store'
|
||||
|
||||
|
||||
// create an axios instance
|
||||
const service = axios.create({
|
||||
baseURL: process.env.WEB_ADDR, // api的base_url
|
||||
timeout: 10000 // request timeout
|
||||
})
|
||||
|
||||
// request interceptor
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
// 设置token
|
||||
config.headers['token'] = getToken()
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
// Do something with request error
|
||||
Promise.reject(error)
|
||||
})
|
||||
|
||||
// respone interceptor
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
return response
|
||||
},
|
||||
error => {
|
||||
var response = error.response
|
||||
if (response == undefined) {
|
||||
Message.error({
|
||||
message: error.message,
|
||||
duration: 3000,
|
||||
customClass: 'network-error'
|
||||
})
|
||||
return Promise.reject(error)
|
||||
}
|
||||
if (response.data.err_code == 1001) {
|
||||
store.dispatch("setNeedSignin", 1)
|
||||
store.dispatch("ClearUserInfo")
|
||||
return Promise.reject(response.data.message+' : '+ response.data.err_code)
|
||||
}
|
||||
|
||||
if (response.data.err_code != 0) {
|
||||
Message(
|
||||
{
|
||||
showClose: true,
|
||||
message: response.data.message+' : '+ response.data.err_code,
|
||||
type: 'error'
|
||||
}
|
||||
)
|
||||
return Promise.reject(response.data.message+' : '+ response.data.err_code)
|
||||
}
|
||||
|
||||
Message.error(error.message)
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
export default service
|
@ -1,230 +0,0 @@
|
||||
<template>
|
||||
<div class="home markdown article-edit">
|
||||
<el-row>
|
||||
<el-col :span="24" :offset="0">
|
||||
<div class="tags no-border">
|
||||
<el-input size="small" v-model="tempArticle.title" class="inline-input width-200" placeholder="Title" @blur="setTitle"></el-input>
|
||||
<el-select class="margin-left-10 width-300" size="small" v-model="tempArticle.tags" multiple filterable remote placeholder="Tags" @change="setTags" :remote-method="queryTags" :loading="tagsLoading" allow-create default-first-option>
|
||||
<el-option v-for="item in tags" :key="item" :label="item" :value="item"></el-option>
|
||||
</el-select>
|
||||
|
||||
<el-select
|
||||
v-model="tempArticle.lang"
|
||||
placeholder="lang for article"
|
||||
size="small"
|
||||
class="width-150"
|
||||
>
|
||||
<el-option v-for="o in langOptions" :key="o.label" :label="o.label" :value="o.value"></el-option>
|
||||
</el-select>
|
||||
<span>
|
||||
<el-button size="medium" type="info" class="border-radius-100" @click="preview">PREVIEW</el-button>
|
||||
<el-button size="medium" type="info" class="border-radius-100" @click="saveNew(1)" v-show="tempArticle.status == 1 || mode=='new'">SAVE DRAFT</el-button>
|
||||
<el-button size="medium" type="info" class="border-radius-100" @click="saveChanges" v-show="tempArticle.status == 2">SAVE CHANGES</el-button>
|
||||
<el-button size="medium" type="primary" class="border-radius-100" @click="saveNew(2)" v-show="tempArticle.status != 2">PUBLISH</el-button>
|
||||
</span>
|
||||
|
||||
<span class="float-right margin-top-5 margin-right-10 font-size-18">
|
||||
<el-tooltip content="Revert to the previous save" class="margin-right-15" v-show="mode=='edit'"><i class="el-icon-back cursor-pointer" @click="clearChanges" ></i></el-tooltip>
|
||||
<el-tooltip content="Delete this post" v-show="mode=='edit'"><i class="el-icon-delete cursor-pointer"></i></el-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<editor :editorHeight="editorHeight" class="margin-top-5" parent="article" :md="tempArticle.md" @articleSetMD="articleSetMD"></editor>
|
||||
</el-col>
|
||||
<el-col :span="12" v-if="previewReset" class="margin-top-5 render">
|
||||
<render id ="render-content" :content="tempArticle.render" :style="{'height':editorHeight}" class="padding-10 overflow-y-auto"></render>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import render from "../components/render"
|
||||
import editor from "../components/editor"
|
||||
import langOptions from "@/utils/data"
|
||||
export default {
|
||||
components: {render,editor},
|
||||
data () {
|
||||
return {
|
||||
tagsLoading: false,
|
||||
tags: [],
|
||||
allTags: ['go','golang','rust','java','javascript'], // query tags from remote server
|
||||
tempArticle: {
|
||||
title: '',
|
||||
tags: [],
|
||||
md :'',
|
||||
render: '',
|
||||
lang: this.$store.state.misc.lang
|
||||
},
|
||||
tempRender :'',
|
||||
previewReset: false,
|
||||
editorHeight: 'calc(100vh - 125px)',
|
||||
localStoreID : window.location.origin + window.location.pathname,
|
||||
|
||||
// for edit only
|
||||
mode: 'new',
|
||||
arID: '',
|
||||
|
||||
langOptions: langOptions,
|
||||
previewed : false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"$store.state.user.id"() {
|
||||
if (this.$store.state.user.id != '') {
|
||||
this.init()
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
clearChanges() {
|
||||
request({
|
||||
url: "/web/article/beforeEdit",
|
||||
method: "GET",
|
||||
params: {
|
||||
article_id: this.arID
|
||||
}
|
||||
}).then(res => {
|
||||
this.tempArticle = res.data.data
|
||||
localStorage.removeItem(this.localStoreID)
|
||||
});
|
||||
},
|
||||
articleSetMD(md,render) {
|
||||
this.tempArticle.md = md
|
||||
// console.log(render)
|
||||
this.tempRender = render
|
||||
localStorage.setItem(this.localStoreID, JSON.stringify(this.tempArticle))
|
||||
},
|
||||
preview() {
|
||||
request({
|
||||
url: "/web/post/preview",
|
||||
method: "POST",
|
||||
params: {
|
||||
render: this.tempRender
|
||||
}
|
||||
}).then(res => {
|
||||
this.tempArticle.render = res.data.data
|
||||
this.previewReset = true
|
||||
// make the render area scroll to bottom
|
||||
if (this.previewed) {
|
||||
setTimeout(function() {
|
||||
var r = document.getElementById('render-content')
|
||||
r.scrollTop = r.scrollHeight
|
||||
} ,300)
|
||||
} else {
|
||||
this.previewed = true
|
||||
}
|
||||
});
|
||||
},
|
||||
saveChanges() {
|
||||
if (this.tempArticle.title == '') {
|
||||
this.$message.error('Title cant be blank')
|
||||
return
|
||||
}
|
||||
|
||||
this.tempArticle.render = this.tempRender
|
||||
request({
|
||||
url: "/web/article/saveChanges",
|
||||
method: "POST",
|
||||
params: {
|
||||
content: JSON.stringify(this.tempArticle)
|
||||
}
|
||||
}).then(res => {
|
||||
localStorage.removeItem(this.localStoreID)
|
||||
this.$router.push('/' + res.data.data)
|
||||
});
|
||||
},
|
||||
saveNew(opType) {
|
||||
if (this.tempArticle.title == '') {
|
||||
this.$message.error('Title cant be blank')
|
||||
return
|
||||
}
|
||||
|
||||
this.tempArticle.render = this.tempRender
|
||||
this.tempArticle.cover_image = 'https://res.cloudinary.com/practicaldev/image/fetch/s--irWUM2_k--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://res.cloudinary.com/practicaldev/image/fetch/s--5kGvHb_---/c_imagga_scale%2Cf_auto%2Cfl_progressive%2Ch_420%2Cq_auto%2Cw_1000/https://thepracticaldev.s3.amazonaws.com/i/adfopvch5w18u9lqpev9.jpg'
|
||||
request({
|
||||
url: "/web/article/saveNew",
|
||||
method: "POST",
|
||||
params: {
|
||||
type: opType,
|
||||
content: JSON.stringify(this.tempArticle)
|
||||
}
|
||||
}).then(res => {
|
||||
localStorage.removeItem(this.localStoreID)
|
||||
this.$router.push('/' + res.data.data)
|
||||
});
|
||||
},
|
||||
setTags(val) {
|
||||
if (this.tempArticle.tags.length!=0) {
|
||||
var last = this.tempArticle.tags[this.tempArticle.tags.length-1]
|
||||
if (last.trim() == '') {
|
||||
this.$message.warning("tag cant be blank")
|
||||
this.tempArticle.tags.pop()
|
||||
return
|
||||
}
|
||||
}
|
||||
if (this.tempArticle.tags.length > 3) {
|
||||
this.$message.warning("tags length is limited to 3")
|
||||
this.tempArticle.tags.pop()
|
||||
return
|
||||
}
|
||||
localStorage.setItem(this.localStoreID, JSON.stringify(this.tempArticle))
|
||||
},
|
||||
setTitle() {
|
||||
localStorage.setItem(this.localStoreID, JSON.stringify(this.tempArticle))
|
||||
},
|
||||
queryTags(q) {
|
||||
if (q !== '') {
|
||||
this.tagsLoading = true;
|
||||
setTimeout(() => {
|
||||
this.tagsLoading = false;
|
||||
this.tags = this.allTags.filter(item => {
|
||||
return item.toLowerCase()
|
||||
.indexOf(q.toLowerCase()) > -1;
|
||||
});
|
||||
}, 200);
|
||||
} else {
|
||||
this.tags = [];
|
||||
}
|
||||
},
|
||||
init() {
|
||||
this.arID = this.$route.params.arID;
|
||||
if (this.arID != undefined) {
|
||||
this.mode = 'edit'
|
||||
// check ar already in cache
|
||||
var ar = localStorage.getItem(this.localStoreID)
|
||||
if (ar != null) {
|
||||
this.tempArticle = JSON.parse(ar)
|
||||
} else {
|
||||
request({
|
||||
url: "/web/article/beforeEdit",
|
||||
method: "GET",
|
||||
params: {
|
||||
article_id: this.arID
|
||||
}
|
||||
}).then(res => {
|
||||
this.tempArticle = res.data.data
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.mode == 'new') {
|
||||
var ar = localStorage.getItem(this.localStoreID)
|
||||
if (ar != null) {
|
||||
this.tempArticle = JSON.parse(ar)
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
},
|
||||
}
|
||||
</script>
|
@ -1,361 +0,0 @@
|
||||
<template>
|
||||
<div class="discuss padding-20" >
|
||||
<!-- comment editor -->
|
||||
<div class="write-comment">
|
||||
<editor placeholder="Add to the discussion" editorHeight="200px" parent="discuss" :md="tempComment.md" @discussSetMD="discussSetMD" v-if="!commentPreviewd"></editor>
|
||||
<render paddingTop="46px" paddingLeft="20px" :content="tempComment.render" class="height-200" v-else></render>
|
||||
<span class="position-relative float-right z-index-1000 margin-right-20 header-buttons">
|
||||
<span class="bold-meta-word font-size-12 cursor-pointer" @click="previewComment" v-if="!commentPreviewd">PREVIEW</span>
|
||||
<span class="bold-meta-word font-size-12 cursor-pointer" @click="commentPreviewd=false" v-else>MARKDOWN</span>
|
||||
|
||||
<span class="bold-meta-word font-size-12 cursor-pointer margin-left-10" @click="publishComment">PUBLISH</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sorter font-weight-bold font-size-12 margin-top-30 padding-bottom-5">SORT BY <span>BEST</span></div>
|
||||
<div class="comments" v-if="comments.length>0">
|
||||
<div class="comment margin-top-30" v-for="c in comments" :key="c.id" :style="{'margin-left':c.depth * 23 + 'px'}">
|
||||
<i class="iconfont icon-jiantou_shang cursor-pointer upvote" :class="{'vote-highlighted':c.liked==1}" @click="upvoteComment(c)"></i>
|
||||
<i class="iconfont icon-jiantou_xia cursor-pointer downvote" :class="{'vote-highlighted':c.liked==2}" @click="downvoteComment(c)"></i>
|
||||
|
||||
<div class="header font-size-12">
|
||||
<router-link class="uname text-decoration-none" :to="`/${c.uname}`" v-if="c.status==0">{{c.unickname}}</router-link>
|
||||
<span v-else>[deleted]</span>
|
||||
<span class="margin-left-5">{{c.likes}} agreed · {{c.date}} <i v-if="c.edit_date!=undefined">· edited {{c.edit_date}}</i></span>
|
||||
</div>
|
||||
|
||||
<!-- edit reply editor -->
|
||||
<div class="write-comment reply-comment margin-top-10" v-if="currentEditCommentID == c.id">
|
||||
<editor editorHeight="150px" parent="discuss" :toolbarsShow="false" :md="tempEditReply.md" @discussSetMD="editReplySetMD"></editor>
|
||||
</div>
|
||||
<!-- body and footer, hide when editing -->
|
||||
<render :content="c.render" class="body font-size-14 margin-top-8" v-else></render>
|
||||
<div class="footer font-weight-bold font-size-12 margin-top-10">
|
||||
<span v-if="currentEditCommentID != c.id">
|
||||
<span class="cursor-pointer" @click="reply(c.id)" v-if="c.status!=1">Reply</span>
|
||||
<span class="cursor-pointer margin-left-5 margin-right-10" v-if="$store.state.user.id==c.uid && c.status!=1" @click="editReply(c)">Edit</span>
|
||||
<el-dropdown placement="bottom-start" v-if="$store.state.user.id==c.uid">
|
||||
<span class="el-dropdown-link">
|
||||
<i class="el-icon-more cursor-pointer"></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="deleteComment(c.id)" v-show="c.status!=1"><i class="el-icon-delete" ></i>Delete comment</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="revertComment(c.id)" v-show="c.status==1"><i class="iconfont icon-undo"></i>Revert comment</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
|
||||
<span v-if="currentCommentID == c.id" class="float-right">
|
||||
<span class="cursor-pointer" @click="previewReply" v-if="!replyPreviewd">Preview</span>
|
||||
<span class="cursor-pointer" @click="replyPreviewd=false" v-else>Markdown</span>
|
||||
|
||||
<span class=" cursor-pointer margin-left-5" @click="publishReply(c.id)">Publish</span>
|
||||
</span>
|
||||
</span>
|
||||
<span v-else class="float-right">
|
||||
<span class=" cursor-pointer margin-left-5" @click="cancelEditReply">Cancel</span>
|
||||
<span class=" cursor-pointer margin-left-5" @click="publishEditReply(c.id)">Publish</span>
|
||||
</span>
|
||||
</div>
|
||||
<!-- reply editor -->
|
||||
<div class="write-comment reply-comment margin-top-10" v-if="currentCommentID == c.id">
|
||||
<editor placeholder="Add to the discussion" editorHeight="150px" parent="discuss" :toolbarsShow="false" :md="tempReply.md" @discussSetMD="replySetMD" v-if="!replyPreviewd"></editor>
|
||||
<render :content="tempReply.render" class="height-150" v-else></render>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-align-center padding-top-40 padding-bottom-40 no-comments">
|
||||
<i class="iconfont icon-comments-alt"/>
|
||||
<div class="meta-word font-size-18 margin-top-20" >No Comments Yet</div>
|
||||
<div class="meta-word font-size-16 margin-top-15">Be the first to share what you think!</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import editor from "./editor"
|
||||
import render from "./render"
|
||||
import request from "@/utils/request";
|
||||
export default {
|
||||
props: ['postAuthorID','postID','postType'],
|
||||
components: {editor,render},
|
||||
data() {
|
||||
return {
|
||||
tempComment: {
|
||||
md : '',
|
||||
render: ''
|
||||
},
|
||||
tempCommentRender: '',
|
||||
commentPreviewd : false,
|
||||
|
||||
comments: [],
|
||||
currentCommentID: '',
|
||||
|
||||
tempReply: {
|
||||
md:'',
|
||||
render: ''
|
||||
},
|
||||
replyPreviewd : false,
|
||||
tempReplyRender: '',
|
||||
|
||||
currentEditCommentID: '',
|
||||
tempEditReply: {
|
||||
md: '',
|
||||
render: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
"$store.state.user.id"() {
|
||||
if (this.$store.state.user.id != '') {
|
||||
this.init()
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
revertComment(id) {
|
||||
request({
|
||||
url: "/web/comment/revert",
|
||||
method: "POST",
|
||||
params: {
|
||||
id: id
|
||||
}
|
||||
}).then(res => {
|
||||
for (var i=0;i<this.comments.length;i++) {
|
||||
if (this.comments[i].id == id) {
|
||||
this.comments[i].md = res.data.data.md
|
||||
this.comments[i].render = res.data.data.render
|
||||
this.comments[i].uname = res.data.data.uname
|
||||
this.comments[i].unickname = res.data.data.unickname
|
||||
this.comments[i].status = 0
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
deleteComment(id) {
|
||||
this.$confirm('Are you sure you want to delete your comment?', 'Delete comment', {
|
||||
confirmButtonText: 'DELETE',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning',
|
||||
center: true
|
||||
}).then(() => {
|
||||
request({
|
||||
url: "/web/comment/delete",
|
||||
method: "POST",
|
||||
params: {
|
||||
id: id
|
||||
}
|
||||
}).then(res => {
|
||||
for (var i=0;i<this.comments.length;i++) {
|
||||
if (this.comments[i].id == id) {
|
||||
this.comments[i].status= 1
|
||||
this.comments[i].md = '[Deleted]'
|
||||
this.comments[i].render = '[Deleted]'
|
||||
}
|
||||
}
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
upvoteComment(c) {
|
||||
request({
|
||||
url: "/web/comment/like",
|
||||
method: "POST",
|
||||
params: {
|
||||
id: c.id
|
||||
}
|
||||
}).then(res => {
|
||||
if (c.liked == 0) {
|
||||
c.liked = 1
|
||||
c.likes++
|
||||
} else if (c.liked == 1) {
|
||||
c.liked = 0
|
||||
c.likes --
|
||||
} else {
|
||||
c.liked = 1
|
||||
c.likes = c.likes + 2
|
||||
}
|
||||
});
|
||||
},
|
||||
downvoteComment(c) {
|
||||
request({
|
||||
url: "/web/comment/dislike",
|
||||
method: "POST",
|
||||
params: {
|
||||
id: c.id
|
||||
}
|
||||
}).then(res => {
|
||||
if (c.liked == 0) {
|
||||
c.liked = 2
|
||||
c.likes--
|
||||
} else if (c.liked == 1) {
|
||||
c.liked = 2
|
||||
c.likes = c.likes - 2
|
||||
} else {
|
||||
c.liked = 0
|
||||
c.likes ++
|
||||
}
|
||||
});
|
||||
},
|
||||
previewReply() {
|
||||
this.replyPreviewd = true
|
||||
request({
|
||||
url: "/web/post/preview",
|
||||
method: "POST",
|
||||
params: {
|
||||
render: this.tempReplyRender
|
||||
}
|
||||
}).then(res => {
|
||||
this.tempReply.render = res.data.data
|
||||
});
|
||||
},
|
||||
editReplySetMD(md,render) {
|
||||
this.tempEditReply.md = md
|
||||
this.tempEditReply.render = render
|
||||
},
|
||||
replySetMD(md,render) {
|
||||
this.tempReply.md = md
|
||||
this.tempReplyRender = render
|
||||
},
|
||||
cancelEditReply() {
|
||||
for (var i=0;i<this.comments.length;i++) {
|
||||
if (this.comments[i].id == this.currentEditCommentID) {
|
||||
if (this.comments[i].md != this.tempEditReply.md) {
|
||||
this.$confirm('Are you sure that you want to discard your changes?', 'Cancel Edit', {
|
||||
confirmButtonText: 'Discard',
|
||||
cancelButtonText: 'Keep',
|
||||
type: 'warning',
|
||||
center: true
|
||||
}).then(() => {
|
||||
this.currentEditCommentID = ''
|
||||
this.tempEditReply.md = ''
|
||||
}).catch(() => {
|
||||
});
|
||||
} else {
|
||||
this.currentEditCommentID = ''
|
||||
this.tempEditReply.md = ''
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
editReply(c) {
|
||||
this.currentEditCommentID = c.id
|
||||
this.currentCommentID = ''
|
||||
this.tempEditReply = {
|
||||
md: c.md,
|
||||
render: ''
|
||||
}
|
||||
},
|
||||
reply(id) {
|
||||
if (id == this.currentCommentID) {
|
||||
this.currentCommentID = ''
|
||||
return
|
||||
}
|
||||
this.currentCommentID = id
|
||||
this.currentEditCommentID = ''
|
||||
},
|
||||
publishEditReply(id) {
|
||||
request({
|
||||
url: "/web/comment/edit",
|
||||
method: "POST",
|
||||
params: {
|
||||
id: id,
|
||||
content: JSON.stringify(this.tempEditReply)
|
||||
}
|
||||
}).then(res => {
|
||||
this.currentEditCommentID = ''
|
||||
for (var i=0;i<this.comments.length;i++) {
|
||||
if (this.comments[i].id == id) {
|
||||
this.comments[i].md = this.tempEditReply.md
|
||||
this.comments[i].render = this.tempEditReply.render
|
||||
}
|
||||
}
|
||||
this.tempEditReply = {
|
||||
md: '',
|
||||
render: ''
|
||||
}
|
||||
});
|
||||
},
|
||||
publishReply(id) {
|
||||
this.tempReply.render = this.tempReplyRender
|
||||
request({
|
||||
url: "/web/comment/reply",
|
||||
method: "POST",
|
||||
params: {
|
||||
pid: id,
|
||||
post_id: this.postID,
|
||||
post_type: this.postType,
|
||||
content: JSON.stringify(this.tempReply)
|
||||
}
|
||||
}).then(res => {
|
||||
this.tempReply = {
|
||||
md : '',
|
||||
render: ''
|
||||
}
|
||||
this.tempReplyRender = ''
|
||||
this.replyPreviewd = false
|
||||
this.currentCommentID = ''
|
||||
var newComments = []
|
||||
for (var i=0;i<this.comments.length;i++) {
|
||||
newComments.push(this.comments[i])
|
||||
if (this.comments[i].id == res.data.data.pid) {
|
||||
res.data.data.depth = this.comments[i].depth + 1
|
||||
newComments.push(res.data.data)
|
||||
}
|
||||
}
|
||||
this.comments = newComments
|
||||
});
|
||||
},
|
||||
publishComment() {
|
||||
this.tempComment.render = this.tempCommentRender
|
||||
request({
|
||||
url: "/web/comment/create",
|
||||
method: "POST",
|
||||
params: {
|
||||
post_id: this.postID,
|
||||
post_type: this.postType,
|
||||
content: JSON.stringify(this.tempComment)
|
||||
}
|
||||
}).then(res => {
|
||||
this.tempComment = {
|
||||
md : '',
|
||||
render: ''
|
||||
}
|
||||
this.tempCommentRender = ''
|
||||
this.commentPreviewd = false
|
||||
this.comments.unshift(res.data.data)
|
||||
});
|
||||
},
|
||||
previewComment() {
|
||||
this.commentPreviewd = true
|
||||
request({
|
||||
url: "/web/post/preview",
|
||||
method: "POST",
|
||||
params: {
|
||||
render: this.tempCommentRender
|
||||
}
|
||||
}).then(res => {
|
||||
this.tempComment.render = res.data.data
|
||||
});
|
||||
},
|
||||
discussSetMD(md,render) {
|
||||
this.tempComment.md = md
|
||||
this.tempCommentRender = render
|
||||
},
|
||||
init() {
|
||||
request({
|
||||
url: "/web/comment/query",
|
||||
method: "GET",
|
||||
params: {
|
||||
post_id: this.postID,
|
||||
}
|
||||
}).then(res => {
|
||||
this.comments = res.data.data
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,58 +0,0 @@
|
||||
<template>
|
||||
<div class="component-editor">
|
||||
<mavon-editor ref="areditor" :style="{height:editorHeight}" :language="$store.state.misc.lang" :value="md" :ishljs = "true" :toolbars="toolbars" :toolbarsFlag="toolbarsShow" :tabSize="2" @change="setMD" :subfield="false" @imgAdd="imgAdd" :placeholder="placeholder"></mavon-editor>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['md','parent','editorHeight',"placeholder","toolbarsShow"],
|
||||
data() {
|
||||
return {
|
||||
toolbars: {
|
||||
bold: false, // 粗体
|
||||
italic: true, // 斜体
|
||||
header: false, // 标题
|
||||
underline: true, // 下划线
|
||||
strikethrough: true, // 中划线
|
||||
mark: true, // 标记
|
||||
superscript: true, // 上角标
|
||||
subscript: true, // 下角标
|
||||
quote: false, // 引用
|
||||
ol: false, // 有序列表
|
||||
ul: false, // 无序列表
|
||||
link: true, // 链接
|
||||
imagelink: true, // 图片链接
|
||||
code: true, // code
|
||||
table: true, // 表格
|
||||
/* 2.1.8 */
|
||||
alignleft: true, // 左对齐
|
||||
aligncenter: true, // 居中
|
||||
alignright: true, // 右对齐
|
||||
help: true
|
||||
},
|
||||
mdSetted: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
setMD(md,render) {
|
||||
var _this = this
|
||||
if (!this.mdSetted) {
|
||||
setTimeout(function() {
|
||||
_this.mdSetted = true
|
||||
_this.$emit(_this.parent + 'SetMD',md,_this.$refs.areditor.d_render)
|
||||
},200)
|
||||
} else {
|
||||
this.$emit(this.parent + 'SetMD',md,this.$refs.areditor.d_render)
|
||||
}
|
||||
},
|
||||
imgAdd: function(fn, _) {
|
||||
// this.$refs.areditor.$img2Url(fn, "http://test.ccd");
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,39 +0,0 @@
|
||||
<template>
|
||||
<div class="component-render overflow-y-auto">
|
||||
<div class="content markdown-body" id="render-content" v-html="content" @click="viewImg" :style="{'padding-top':paddingTop,'padding-left':paddingLeft}"></div>
|
||||
<el-dialog class="white-bg-modal image-modal" :visible.sync="imageModalVisible" top="5vh">
|
||||
<el-row align="middle" justify="center" @click.native="cancelViewImage">
|
||||
<el-col :xs="{span:24,offset:0}" :sm="{span:24,offset:0}" :md="{span: 24,offset:0}" :lg="{ span: 24, offset: 0 }">
|
||||
<img :src="currentImg" alt="" class="width-100p"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['content','paddingTop','paddingLeft'],
|
||||
data() {
|
||||
return {
|
||||
imageModalVisible: false,
|
||||
currentImg: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
viewImg: function(e) {
|
||||
if (e.srcElement.localName == "img") {
|
||||
this.imageModalVisible = true;
|
||||
this.currentImg = e.srcElement.currentSrc;
|
||||
}
|
||||
},
|
||||
cancelViewImage() {
|
||||
this.imageModalVisible = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,69 +0,0 @@
|
||||
<template>
|
||||
<div class="user-card padding-10" :style="{'border': '1px solid ' + user.text_color,'box-shadow':'1px 1px 0px ' +user.text_color }">
|
||||
<div>
|
||||
<el-avatar
|
||||
:src="user.avatar"
|
||||
slot="reference"
|
||||
class="display-inline-block vertical-align-middle cursor-pointer"
|
||||
@click.native="userHome"
|
||||
></el-avatar>
|
||||
<router-link :to="'/' + user.name" class="position-absolute margin-left-10 font-weight-500 cursor-pointer text-decoration-none">{{user.nickname}}</router-link>
|
||||
<router-link :to="'/' + user.name" class="position-absolute margin-top-25 margin-left-10 font-size-14 cursor-pointer text-decoration-none">@{{user.name}}</router-link >
|
||||
</div>
|
||||
<div class="margin-top-15 margin-left-10" v-html="user.about" v-if="user.about!='' && user.about!=undefined">
|
||||
</div>
|
||||
<div class="text-align-center padding-top-10 padding-bottom-10 font-weight-bold border-radius-3 cursor-pointer margin-top-10" :style="{'background-color':user.bg_color,'color':followColor()}">FOLLOW</div>
|
||||
|
||||
<div class="margin-top-10 margin-left-10" v-if="user.website!='' && user.website!=undefined">
|
||||
<div class="color-regular font-weight-500">website</div>
|
||||
<div>{{user.website}}</div>
|
||||
</div>
|
||||
|
||||
<div class="margin-top-10 margin-left-10" v-if="user.employer!='' && user.employer!=undefined">
|
||||
<div class="color-regular font-weight-500">work</div>
|
||||
<div v-html="user.employer"></div>
|
||||
</div>
|
||||
|
||||
<div class="margin-top-10 margin-left-10" v-if="user.education!='' && user.education!=undefined">
|
||||
<div class="color-regular font-weight-500">education</div>
|
||||
<div v-html="user.education"></div>
|
||||
</div>
|
||||
<el-divider></el-divider>
|
||||
<el-row class="margin-top-10 padding-left-10 padding-right-10">
|
||||
<el-col :span="12">
|
||||
<div class="color-regular font-weight-500">location</div>
|
||||
<div><i class="el-icon-location" :style="{color:user.text_color}"></i><span class="font-size-14">{{user.location}}</span></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="color-regular font-weight-500">joined</div>
|
||||
<div><i class="el-icon-date margin-right-5" :style="{color:user.text_color}"></i><span class="font-size-14">{{user.create_date}}</span></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
export default {
|
||||
props: ['user'],
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
followColor() {
|
||||
if (this.user.bg_color == '#000' && this.user.text_color=='#000') {
|
||||
return '#fff'
|
||||
}
|
||||
return this.user.text_color
|
||||
},
|
||||
userHome() {
|
||||
this.$router.push('/' + this.user.name)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,103 +0,0 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<el-row>
|
||||
<el-col :span="20" :offset="2">
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
<p>content</p>
|
||||
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Home',
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,24 +0,0 @@
|
||||
<template>
|
||||
<div class="setting-account margin-top-20">
|
||||
<el-card shadow="hover">
|
||||
<div>aaaa</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,55 +0,0 @@
|
||||
<template>
|
||||
<div class="setting-nav">
|
||||
<el-row>
|
||||
<el-col :span="20" :offset="2">
|
||||
<div class="header padding-bottom-10 border-bottom" >
|
||||
<h3 class="big-title margin-bottom-30"><i class="el-icon-s-tools margin-right-10"></i>User Settings</h3>
|
||||
<span v-for="i in items" :key="i" :class="{'selected': selItem==i,'meta-word':selItem!=i}" class="cursor-pointer item font-weight-500" @click="selectItem(i)">{{names[i]}}</span>
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
items: [],
|
||||
level: {},
|
||||
|
||||
path : '',
|
||||
selItem : '',
|
||||
|
||||
|
||||
appNames: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.initItem()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
selectItem(i) {
|
||||
this.$router.push('/dev/setting/' + i)
|
||||
},
|
||||
initItem() {
|
||||
this.path = window.location.pathname
|
||||
this.items = ['account','profile']
|
||||
this.level = {account:2,profile:2}
|
||||
this.names = {account: 'Account',profile:'Profile'}
|
||||
this.selItem = this.path.split('/')[3]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initItem()
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -1,151 +0,0 @@
|
||||
<template>
|
||||
<div class="setting-profile margin-top-20">
|
||||
<el-row v-if="user.id!=undefined">
|
||||
<el-col :span="13" class="padding-left-20 padding-right-20">
|
||||
<div>
|
||||
<h4>Display name</h4>
|
||||
<div class="meta-word font-size-12">Set a display name. This does not change your username.</div>
|
||||
<el-input size="medium" class="margin-top-5 margin-bottom-5" v-model="user.nickname" :maxlength="30"></el-input>
|
||||
<div class="meta-word font-size-12">{{30-user.nickname.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<h4>About</h4>
|
||||
<div class="meta-word font-size-12">A brief description of yourself shown on your profile.</div>
|
||||
<el-input type="textarea" class="margin-top-5 margin-bottom-5" v-model="user.about" :maxlength="500"></el-input>
|
||||
<div class="meta-word font-size-12">{{500-user.about.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<h4>Website url</h4>
|
||||
<el-input size="medium" placeholder="https://yoursite.com" v-model="user.website" :maxlength="30"></el-input>
|
||||
<div class="meta-word font-size-12 margin-top-5">{{30-user.website.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<h4>Location </h4>
|
||||
<el-input size="medium" placeholder="Your location" v-model="user.location" :maxlength="30"></el-input>
|
||||
<div class="meta-word font-size-12 margin-top-5">{{30-user.location.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-30">
|
||||
<h4>Background color</h4>
|
||||
<el-color-picker @change="changBgColor" color-format="hex" class="position-absolute" size="small" v-model="user.bg_color"></el-color-picker>
|
||||
<span class="meta-word font-size-12 margin-left-40">The background color used in your home page</span>
|
||||
</div>
|
||||
<div class="margin-top-30 margin-bottom-50">
|
||||
<h4>Text color </h4>
|
||||
<el-color-picker @change="changTextColor" color-format="hex" class="position-absolute" size="small" v-model="user.text_color"></el-color-picker>
|
||||
<span class="meta-word font-size-12 margin-left-40">The text color used in your home page</span>
|
||||
</div>
|
||||
|
||||
<el-divider content-position="left" >Job/Working</el-divider>
|
||||
<div class="margin-top-40">
|
||||
<h4>Education</h4>
|
||||
<div class="meta-word font-size-12">A brief description of your education.</div>
|
||||
<el-input type="textarea" class="margin-top-5 margin-bottom-5" v-model="user.education" :maxlength="500"></el-input>
|
||||
<div class="meta-word font-size-12">{{500-user.education.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<h4>Employer</h4>
|
||||
<div class="meta-word font-size-12">e.g : Development Team Leader at <a href="https://google.com">Google</a></div>
|
||||
<el-input type="textarea" class="margin-top-5 margin-bottom-5" v-model="user.employer" :maxlength="500"></el-input>
|
||||
<div class="meta-word font-size-12">{{500-user.employer.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<h4>Skills </h4>
|
||||
<div class="meta-word font-size-12">What programming skills do you have? Are your a expert?</div>
|
||||
<el-input type="textarea" class="margin-top-5 margin-bottom-5" v-model="user.skills" :maxlength="500"></el-input>
|
||||
<div class="meta-word font-size-12">{{500-user.skills.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<h4>Working Experience</h4>
|
||||
<div class="meta-word font-size-12">Your working experience and the projects you participated</div>
|
||||
<el-input type="textarea" class="margin-top-5 margin-bottom-5" v-model="user.working_exp" :maxlength="500"></el-input>
|
||||
<div class="meta-word font-size-12">{{500-user.working_exp.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<h4>Available for</h4>
|
||||
<div class="meta-word font-size-12">What kinds of collaborations or works are you available for?</div>
|
||||
<el-input type="textarea" class="margin-top-5 margin-bottom-5" v-model="user.available_for" :maxlength="500"></el-input>
|
||||
<div class="meta-word font-size-12">{{500-user.available_for.length}} Characters</div>
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<h4>Looking for work</h4>
|
||||
|
||||
<el-switch
|
||||
class="position-absolute"
|
||||
v-model="user.lfw"
|
||||
active-color="#13ce66">
|
||||
</el-switch>
|
||||
<span class="meta-word font-size-12 margin-left-50">Are you looking for a work now?</span>
|
||||
</div>
|
||||
|
||||
<div class="margin-top-20">
|
||||
<el-button type="primary" @click="setProfile">SUBMIT</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6" :offset="1">
|
||||
<UserCard :user="user"></UserCard>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import UserCard from "../components/user-card";
|
||||
export default {
|
||||
components: {UserCard},
|
||||
data() {
|
||||
return {
|
||||
user: {}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
"$store.state.user.id"() {
|
||||
if (this.$store.state.user.id != '') {
|
||||
this.init()
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changBgColor(val) {
|
||||
if (val==null) {
|
||||
this.user.bg_color='#000'
|
||||
}
|
||||
},
|
||||
changTextColor(val) {
|
||||
if (val==null) {
|
||||
this.user.text_color='#000'
|
||||
}
|
||||
},
|
||||
setProfile() {
|
||||
request({
|
||||
url: "/user/profile/set",
|
||||
method: "POST",
|
||||
params: {
|
||||
user: JSON.stringify(this.user)
|
||||
}
|
||||
}).then(res => {
|
||||
this.$message.success("Saved")
|
||||
});
|
||||
},
|
||||
init() {
|
||||
request({
|
||||
url: "/user/profile",
|
||||
method: "GET",
|
||||
params: {
|
||||
}
|
||||
}).then(res => {
|
||||
this.user = res.data.data
|
||||
if (this.user.lfw ==0) {
|
||||
this.user.lfw = false
|
||||
} else {
|
||||
this.user.lfw = true
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|