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