pull/43/head
sunface 5 years ago
parent 2701a556b0
commit 1d1fc6d06e

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

14
ui_old/.gitignore vendored

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

Binary file not shown.

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>

11727
ui_old/package-lock.json generated

File diff suppressed because it is too large Load Diff

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

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";
}

@ -1,41 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="undo" unicode="&#58931;" d="M761.856-128c113.728 206.048 132.896 520.32-313.856 509.824l0-253.824-384 384 384 384 0-248.384c534.976 13.952 594.56-472.224 313.856-775.616z" horiz-adv-x="1024" />
<glyph glyph-name="sousuo" unicode="&#58930;" d="M474.453333 11.946667c-225.28 0-409.6 184.32-409.6 409.6s184.32 409.6 409.6 409.6 409.6-184.32 409.6-409.6-184.32-409.6-409.6-409.6z m0 68.266666c187.733333 0 341.333333 153.6 341.333334 341.333334s-153.6 341.333333-341.333334 341.333333-341.333333-153.6-341.333333-341.333333 153.6-341.333333 341.333333-341.333334z m252.586667-54.613333c-13.653333 13.653333-10.24 37.546667 3.413333 47.786667s37.546667 10.24 47.786667-3.413334l64.853333-78.506666c13.653333-13.653333 10.24-37.546667-3.413333-47.786667s-37.546667-10.24-47.786667 3.413333l-64.853333 78.506667z" horiz-adv-x="1024" />
<glyph glyph-name="comments-alt" unicode="&#58904;" d="M831.914144 448.04623V768.013209c0 70.592715-57.394077 127.986791-127.986792 127.986791H127.986791C57.394077 896 0 838.605923 0 768.013209v-319.966979c0-70.592715 57.394077-127.986791 127.986791-127.986791v-108.388814c0-15.998349 18.198122-25.1974 30.996801-15.59839l165.582912 124.187183H703.927352c70.592715-0.199979 127.986791 57.194097 127.986792 127.786812z m191.980187 127.986792h-127.986791v-127.986792c0-105.789082-86.191105-191.980187-191.980188-191.980187H383.960374v-127.986791c0-70.592715 57.394077-127.986791 127.986791-127.986792h251.374058l165.582911-124.187183c12.798679-9.599009 30.996801-0.399959 30.996801 15.59839V0.09246h63.993396c70.592715 0 127.986791 57.394077 127.986791 127.986792V448.04623c0 70.592715-57.394077 127.986791-127.986791 127.986792z" horiz-adv-x="1152" />
<glyph glyph-name="jiantou_shang" unicode="&#58932;" d="M434.666714 708.530676C297.43919 528.723334 160.191798 348.917799 22.964274 169.110458c-48.854624-64.034092-3.20604-156.297589 77.324255-156.297589h823.421135c80.530295 0 126.198748 92.263496 77.324256 156.297589C863.806396 348.917799 726.559004 528.723334 589.333286 708.530676c-38.933061 51.01125-115.733512 51.01125-154.666572 0z" horiz-adv-x="1024" />
<glyph glyph-name="jiantou_xia" unicode="&#58934;" d="M589.320643 59.487386c137.245586 179.809148 274.469497 359.614683 411.693408 539.422024 48.874492 64.014224 3.225908 156.297589-77.322449 156.297589H100.306592c-80.548357 0-126.195135-92.283365-77.342318-156.297589 137.24378-179.807341 274.467691-359.612876 411.713277-539.422024 38.933061-51.009444 115.711837-51.009444 154.643092 0z" horiz-adv-x="1024" />
</font>
</defs></svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

@ -1,12 +0,0 @@
<svg
id="clap--icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="-549 338 100.1 125"
>
<path
d="M-471.2 366.8c1.2 1.1 1.9 2.6 2.3 4.1.4-.3.8-.5 1.2-.7 1-1.9.7-4.3-1-5.9-2-1.9-5.2-1.9-7.2.1l-.2.2c1.8.1 3.6.9 4.9 2.2zm-28.8 14c.4.9.7 1.9.8 3.1l16.5-16.9c.6-.6 1.4-1.1 2.1-1.5 1-1.9.7-4.4-.9-6-2-1.9-5.2-1.9-7.2.1l-15.5 15.9c2.3 2.2 3.1 3 4.2 5.3zm-38.9 39.7c-.1-8.9 3.2-17.2 9.4-23.6l18.6-19c.7-2 .5-4.1-.1-5.3-.8-1.8-1.3-2.3-3.6-4.5l-20.9 21.4c-10.6 10.8-11.2 27.6-2.3 39.3-.6-2.6-1-5.4-1.1-8.3z"
/>
<path
d="M-527.2 399.1l20.9-21.4c2.2 2.2 2.7 2.6 3.5 4.5.8 1.8 1 5.4-1.6 8l-11.8 12.2c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l34-35c1.9-2 5.2-2.1 7.2-.1 2 1.9 2 5.2.1 7.2l-24.7 25.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l28.5-29.3c2-2 5.2-2 7.1-.1 2 1.9 2 5.1.1 7.1l-28.5 29.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.4 1.7 0l24.7-25.3c1.9-2 5.1-2.1 7.1-.1 2 1.9 2 5.2.1 7.2l-24.7 25.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l14.6-15c2-2 5.2-2 7.2-.1 2 2 2.1 5.2.1 7.2l-27.6 28.4c-11.6 11.9-30.6 12.2-42.5.6-12-11.7-12.2-30.8-.6-42.7m18.1-48.4l-.7 4.9-2.2-4.4m7.6.9l-3.7 3.4 1.2-4.8m5.5 4.7l-4.8 1.6 3.1-3.9"
/>
</svg>

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,50 +0,0 @@
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
// import 'mavon-editor/dist/markdown/github-markdown.min.css'
Vue.use(mavonEditor)
import './assets/icon/iconfont.css';
import App from './App'
Vue.use(ElementUI);
import router from './router'
// 全局范围加载通用样式每个vue page里无需重复引入
import '!style-loader!css-loader!less-loader!./theme/eleui-style.less'
import '!style-loader!css-loader!less-loader!./theme/style.less'
Vue.config.productionTip = false
import i18n from './lang' // Internationalization
import store from './store'
router.beforeEach((to, _, next) => {
next()
})
router.afterEach(() => {
})
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
i18n,
components: { App },
template: '<App/>'
})

@ -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,80 +0,0 @@
/* eslint-disable */
import { getToken, setToken, removeToken } from '@/utils/auth'
import request from '@/utils/request'
import Cookies from 'js-cookie'
const user = {
state: {
id: Cookies.get('imdev-userid') || '',
name: Cookies.get('imdev-name') || '',
nickname: Cookies.get('imdev-nickname') || '',
avatar: Cookies.get('imdev-avatar') || '',
token: getToken() || ''
},
mutations: {
SET_USERID: (state,userID) => {
Cookies.set('imdev-userid', userID)
state.id = userID
},
SET_NAME: (state, name) => {
Cookies.set('imdev-name', name)
state.name = name
},
SET_NICKNAME: (state, name) => {
Cookies.set('imdev-nickname', name)
state.nickname = name
},
SET_AVATAR: (state, avatar) => {
Cookies.set('imdev-avatar', avatar)
state.avatar = avatar
},
SET_TOKEN: (state, token) => {
state.token = token
setToken(token)
}
},
actions: {
setToken({ commit }, token) {
commit('SET_TOKEN', token)
},
// SSO登陆成功保存信息
SetUserInfo({ commit,state},userInfo) {
return new Promise(resolve => {
setToken(userInfo.token)
commit('SET_TOKEN', userInfo.token)
commit('SET_USERID', userInfo.id)
commit('SET_NAME', userInfo.name)
commit('SET_NICKNAME', userInfo.nickname)
commit('SET_AVATAR', userInfo.avatar)
resolve()
})
},
ClearUserInfo({ commit,state},userInfo) {
removeToken()
commit('SET_TOKEN', '')
commit('SET_USERID', '')
commit('SET_NAME', '')
commit('SET_NICKNAME', '')
commit('SET_AVATAR', '')
},
// 登出
SignOut({ commit, state }) {
return request({
url: '/web/signOut',
method: 'post',
params:{
}
}).then(res => {
removeToken()
commit('SET_TOKEN', '')
commit('SET_USERID', '')
commit('SET_NAME', '')
commit('SET_NICKNAME', '')
commit('SET_AVATAR', '')
})
}
}
}
export default user

@ -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,153 +0,0 @@
<template>
<div class="article-detail">
<el-row :gutter="20">
<el-col
:xs="{span:1,offset:0}"
:sm="{span:1,offset:0}"
:md="{span: 1,offset:2}"
:lg="{ span: 1, offset: 2 }"
>
<div class="squares position-fixed z-index-100 margin-top-100">
<div class="square font-hover-primary">
<button id="clap" :class="{clap:true, liked: arDetail.liked}" @click="arLike">
<span>
<svg
id="clap--icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="-549 338 100.1 125"
>
<path
d="M-471.2 366.8c1.2 1.1 1.9 2.6 2.3 4.1.4-.3.8-.5 1.2-.7 1-1.9.7-4.3-1-5.9-2-1.9-5.2-1.9-7.2.1l-.2.2c1.8.1 3.6.9 4.9 2.2zm-28.8 14c.4.9.7 1.9.8 3.1l16.5-16.9c.6-.6 1.4-1.1 2.1-1.5 1-1.9.7-4.4-.9-6-2-1.9-5.2-1.9-7.2.1l-15.5 15.9c2.3 2.2 3.1 3 4.2 5.3zm-38.9 39.7c-.1-8.9 3.2-17.2 9.4-23.6l18.6-19c.7-2 .5-4.1-.1-5.3-.8-1.8-1.3-2.3-3.6-4.5l-20.9 21.4c-10.6 10.8-11.2 27.6-2.3 39.3-.6-2.6-1-5.4-1.1-8.3z"
/>
<path
d="M-527.2 399.1l20.9-21.4c2.2 2.2 2.7 2.6 3.5 4.5.8 1.8 1 5.4-1.6 8l-11.8 12.2c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l34-35c1.9-2 5.2-2.1 7.2-.1 2 1.9 2 5.2.1 7.2l-24.7 25.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l28.5-29.3c2-2 5.2-2 7.1-.1 2 1.9 2 5.1.1 7.1l-28.5 29.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.4 1.7 0l24.7-25.3c1.9-2 5.1-2.1 7.1-.1 2 1.9 2 5.2.1 7.2l-24.7 25.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l14.6-15c2-2 5.2-2 7.2-.1 2 2 2.1 5.2.1 7.2l-27.6 28.4c-11.6 11.9-30.6 12.2-42.5.6-12-11.7-12.2-30.8-.6-42.7m18.1-48.4l-.7 4.9-2.2-4.4m7.6.9l-3.7 3.4 1.2-4.8m5.5 4.7l-4.8 1.6 3.1-3.9"
/>
</svg>
</span>
</button>
<span class="position-absolute meta-word font-size-13 likes margin-left-30 margin-top--30 font-weight-bold">{{arDetail.likes}}</span>
</div>
<div v-show="arDetail.uid==this.$store.state.user.id" class="square cursor-pointer margin-top-20">
<a>
<el-tooltip content="编辑文章" placement="right">
<router-link :to="'/'+this.authorInfo.name + '/' + this.arID + '/edit'"><i class="el-icon-edit cursor-pointer"></i></router-link>
</el-tooltip>
</a>
</div>
<div class="square font-hover-primary padding-top-10">
<el-tooltip content="加入书签" placement="right">
<i class="el-icon-star-off cursor-pointer"></i>
</el-tooltip>
</div>
<div class="square font-hover-primary padding-top-10" >
<el-tooltip content="Discuss" placement="right">
<a href="#discuss"><i class="el-icon-s-comment cursor-pointer"></i></a>
</el-tooltip>
</div>
</div>
</el-col>
<el-col
:xs="{span:22,offset:2}"
:sm="{span:17,offset:3}"
:md="{span: 13,offset:4}"
:lg="{ span: 13, offset: 4 }"
>
<img :src="arDetail.cover_image" class="width-100p"></img>
<h1 class=" margin-top-30">{{arDetail.title}}</h1>
<div class="margin-left-5">
<span class="vertical-align-middle display-inline-block"><img :src="authorInfo.avatar" alt="" class="height-40 width-40"></span>
<span class="meta-word font-size-14 font-weight-500">{{arDetail.publish_date}}<span> · {{arDetail.words}} words</span> <span v-if="arDetail.edit_date!=''">· Updated on {{arDetail.edit_date}}</span></span>
</div>
<render :content="arDetail.render" style="min-height:400px" class="min-height-400 margin-top-20 padding-left-8"></render>
</el-col>
<el-col :span="1" :offset="1">
<UserCard class="user-card z-index-100 position-fixed margin-top-40 max-width-280 margin-left-20" :user="authorInfo"></UserCard>
</el-col>
</el-row>
<el-row class="discuss margin-top-40">
<el-col
:xs="{span:22,offset:2}"
:sm="{span:17,offset:3}"
:md="{span: 13,offset:4}"
:lg="{ span: 13, offset: 4 }"
>
<discuss id="discuss" :postID="this.arID" postType="1" :postAuthorID="authorInfo.id"></discuss>
</el-col>
</el-row>
</div>
</template>
<script>
import request from "@/utils/request";
import render from "../components/render";
import discuss from "../components/discuss";
import UserCard from "../components/user-card";
export default {
components: { render,discuss,UserCard},
data() {
return {
arID: "", // unique article id
arDetail: {},
bookmarked: false,
authorInfo : {},
};
},
watch: {
$route() {
//
},
},
computed: {},
methods: {
arLike() {
var tp = 1 // like
if (this.arDetail.liked) {
tp = 2 //dislike
}
request({
url: "/article/like",
method: "POST",
params: {
id: this.arID,
type: tp
}
}).then(_ => {
this.arDetail.liked = !this.arDetail.liked
});
}
},
beforeDestroy() {
this.$store.dispatch("setNavFixed", true)
},
created() {
this.$store.dispatch("setNavFixed", false)
this.arID = this.$route.params.arID;
request({
url: "/web/article/detail",
method: "GET",
params: {
article_id: this.arID
}
}).then(res0 => {
request({
url: "/web/user/card",
method: "GET",
params: {
uid: res0.data.data.uid
}
}).then(res => {
this.arDetail = res0.data.data;
console.log(this.arDetail)
this.authorInfo = res.data.data
});
});
},
mounted() {
},
};
</script>

@ -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 &nbsp;·&nbsp; {{c.date}} &nbsp; <i v-if="c.edit_date!=undefined">·&nbsp;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,242 +0,0 @@
<template>
<div class="global-nav">
<transition name="fade">
<el-row
v-show="toTop"
:class="{'nav':'true','inTop':inTop,'toTop': toTop}"
type="flex"
align="middle"
>
<el-col
:xs="{span:4}"
:sm="{span:7,offset:1}"
:md="{span: 2,offset:1}"
:lg="{ span: 2, offset: 1 }"
>
<router-link to="/">
<img src="../assets/logo.png" class="cursor-pointer height-45" />
</router-link>
</el-col>
<el-col
:xs="{span:10,offset:4}"
:sm="{span:8}"
:md="{span: 4}"
:lg="{ span: 7,offset:2}"
class
>
<el-input
v-model="searchContent"
prefix-icon="el-icon-search"
:placeholder="$t('nav.navSearchHolder')"
size="medium"
></el-input>
</el-col>
<el-col :span="10">
<span class="float-right">
<el-popover placement="bottom" trigger="hover" class="margin-right-20">
<el-form label-width="110px">
<el-form-item :label="$t('nav.setLang')">
<el-radio-group v-model="currentLang" size="medium" @change="changeLang">
<el-radio-button label="en">English</el-radio-button>
<el-radio-button label="zh">Chinese</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('nav.setTheme')">
<el-select
v-model="currentTheme"
placeholder="theme.."
size="medium"
class="width-150"
:popper-append-to-body="false"
@change="changeTheme"
>
<el-option label="Light" value="light"></el-option>
<el-option label="Dark" value="dark"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('nav.readingLang')">
<el-select
v-model="currentReadingLang"
placeholder="Reading Lang.."
size="medium"
class="width-200"
multiple
:popper-append-to-body="false"
@change="changeReadingLang"
>
<el-option
v-for="o in langOptions"
:key="o.label"
:label="o.label"
:value="o.value"
></el-option>
</el-select>
</el-form-item>
</el-form>
<i class="el-icon-more-outline cursor-pointer" slot="reference"></i>
</el-popover>
<router-link
v-if="this.$store.state.user.token!=''"
to="/dev/article/new"
class="margin-right-20 write-post"
>WRITE A POST</router-link>
<el-button
v-if="this.$store.state.user.token==''"
type="primary"
@click="signInModalVisible=true"
>{{$t('nav.signIn')}}</el-button>
<el-popover v-else placement="bottom" trigger="hover" class="user-menu">
<div class="user-panel font-size-18">
<div><router-link class="margin-top-5 text-decoration-none color-regular" to="/dev/setting">@{{this.$store.state.user.name}}</router-link></div>
<el-divider></el-divider>
<div class="margin-top-5"><router-link class=" text-decoration-none color-regular" to="/dev/setting">Dashboard</router-link></div>
<div class="margin-top-5"><router-link class=" text-decoration-none color-regular" to="/dev/setting">Write A Post</router-link></div>
<div class="margin-top-5"><router-link class=" text-decoration-none color-regular" to="/dev/setting">Reading List</router-link></div>
<div class="margin-top-5"><router-link class=" text-decoration-none color-regular" to="/dev/setting">Settings</router-link></div>
<el-divider></el-divider>
<div><router-link class="text-decoration-none color-regular" to="/dev/setting">About im.dev</router-link></div>
<el-divider></el-divider>
<div class="cursor-pointer" @click.stop="signOut">Sign Out</div>
</div>
<el-avatar
:src="this.$store.state.user.avatar"
slot="reference"
class="display-inline-block vertical-align-middle cursor-pointer"
></el-avatar>
</el-popover>
</span>
</el-col>
</el-row>
</transition>
<router-view class="main-view padding-top-55"></router-view>
<el-dialog class="white-bg-modal sign-in-modal" :visible.sync="signInModalVisible">
<el-row class="sign-in-panel text-align-center padding-top-20 padding-bottom-20">
<el-col :span="10" :offset="7">
<h2 class="padding-top-20">{{$t('nav.signInTitle')}}</h2>
<p class="padding-top-10">{{$t('nav.whySignIn')}}</p>
<div class="padding-top-20">
<el-button type="primary" icon="el-icon-github" @click="signIn">Sign in with Github</el-button>
</div>
<p class="padding-top-20">{{$t('nav.signInFooter')}}</p>
</el-col>
</el-row>
</el-dialog>
</div>
</template>
<script>
import request from "@/utils/request";
import langOptions from "@/utils/data";
export default {
name: "Nav",
data() {
return {
theme: this.$store.state.misc.theme,
searchContent: "",
signInModalVisible: false,
currentLang: this.$store.state.misc.lang,
currentReadingLang: this.$store.state.misc.readingLang,
currentTheme: this.$store.state.misc.theme,
// nav fixed to top
scrollTop: 0,
toTop: true,
topCount: 0,
inTop: true,
langOptions: langOptions
};
},
watch: {
"$store.state.misc.needSignin"() {
this.signInModalVisible = true;
},
"$store.state.misc.navFixed"() {
if (this.$store.state.misc.navFixed) {
window.removeEventListener("scroll", this.handleScroll);
this.inTop = true;
this.toTop = true;
} else {
window.addEventListener("scroll", this.handleScroll);
}
}
},
computed: {},
methods: {
signOut() {
this.$store.dispatch("SignOut");
},
signIn() {
request({
url: "/web/signIn",
method: "POST",
params: {}
}).then(res => {
this.$store.dispatch("SetUserInfo", res.data.data).then(() => {
this.signInModalVisible = false;
});
});
},
changeReadingLang(val) {
this.$store.dispatch("setReadingLang", val);
window.location.reload();
},
changeLang(val) {
this.$store.dispatch("setLang", val);
this.$i18n.locale = val;
window.location.reload();
},
changeTheme(val) {
this.$store.dispatch("setTheme", val);
window.location.reload();
},
loadTheme() {
// vue page
if (this.theme == "light") {
require("!style-loader!css-loader!less-loader!../theme/light/style.less");
require("!style-loader!css-loader!less-loader!../theme/light/eleui-style.less");
} else {
require("!style-loader!css-loader!less-loader!../theme/dark/style.less");
}
},
handleScroll: function(e) {
var y = window.scrollY;
if (y < 1) {
if (!this.inTop) {
this.inTop = true;
}
} else {
if (this.inTop) {
this.inTop = false;
}
}
if (y - this.scrollTop < 0) {
if (!this.toTop) {
// \
this.topCount = this.topCount + 1;
if (this.topCount >= 9) {
this.toTop = true;
this.topCount = 0;
}
}
} else {
if (window.scrollY < 30) {
return;
}
this.toTop = false;
this.topCount = 0;
}
this.scrollTop = y;
}
},
mounted() {
this.loadTheme();
// window.addEventListener('scroll', this.handleScroll);
}
};
</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 &lt;a href="https://google.com"&gt;Google&lt;/a&gt;</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>

@ -1,68 +0,0 @@
<template>
<div class="app-container">
<div style="margin-top:300px;" class="margin-left-20">{{hello}} {{world}}</div>
<div style="margin-left:45%">
{{world}}
<div class="margin-left-20">{{getAddr}}</div>
你好中国人
</div>
</div>
</template>
<script>
import request from '@/utils/request' 
export default {
name: 'tmpl',
data () {
return {
hello: '',
world: ''
}
},
watch: {
$route() {
//
},
world(val) {
// world
}
},
computed: {
getAddr() {
return process.env.API_ADDR
}
},
methods: {
},
mounted() {
this.$store.dispatch('setService', 'hello')
this.hello = this.$store.state.misc.service
this.world = this.$t('common.test')
setTimeout(() => {
this.world = "new world"
}, 3000)
request({
url: '/signIn',
method: 'POST',
params: {
user: '111'
}
}).then(res => {
})
}
}
</script>
<style lang="less" scoped>
// @import "../theme/light/var.less";
.margin-left-20 {
margin-left: 100px
}
</style>
Loading…
Cancel
Save