first commit
This commit is contained in:
parent
509773ccbf
commit
f1f9648a06
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-row class="wrapper">
|
||||
<el-col :xs="24" :sm="24" :xl="24" style="margin: 0 auto;">
|
||||
<el-col v-for="article in articles.data" :key="article.idArticle" style="padding-bottom: 1rem;">
|
||||
<el-col v-for="article in articles.articles" :key="article.idArticle" style="padding-bottom: 1rem;">
|
||||
<el-card>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<el-link @click="onRouter('article',article.articleLink)" :underline="false" style="margin-bottom: .5rem;">
|
||||
@ -36,10 +36,10 @@
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div class="vertical-container text-center">
|
||||
<el-pagination v-show="pagination.total > 10" v-model="pagination"
|
||||
<el-pagination v-show="articles.pagination.total > 10" v-model="articles.pagination"
|
||||
layout="prev, pager, next"
|
||||
:current-page="pagination.currentPage"
|
||||
:total="pagination.total"
|
||||
:current-page="articles.pagination.currentPage"
|
||||
:total="articles.pagination.total"
|
||||
@current-change="currentChange">
|
||||
</el-pagination>
|
||||
</div>
|
||||
@ -49,29 +49,32 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default Vue.extend({
|
||||
name: "PcAside",
|
||||
data() {
|
||||
return {
|
||||
export default {
|
||||
name: "ArticleList",
|
||||
props: {
|
||||
articles: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
articles: state => state.article.list.data,
|
||||
pagination: state => state.article.list.data.pagination
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
currentChange(p) {
|
||||
console.log(p);
|
||||
currentChange(page) {
|
||||
this.$emit('currentChange', page);
|
||||
},
|
||||
onRouter(name, data) {
|
||||
if ("article" === name) {
|
||||
this.$router.push({
|
||||
path: data
|
||||
})
|
||||
} else {
|
||||
this.$router.push(
|
||||
{
|
||||
path: '/user/' + data
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
@ -17,7 +17,7 @@
|
||||
import MobileFooter from "./footer";
|
||||
|
||||
export default {
|
||||
name: "moblieMain",
|
||||
name: "mobileMain",
|
||||
components: {MobileFooter, MobileHeader}
|
||||
}
|
||||
</script>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<header-view/>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<aside-view key="aside"/>
|
||||
<nuxt :nuxt-child-key="$route.name" />
|
||||
</el-main>
|
||||
<el-footer>
|
||||
<footer-view/>
|
||||
@ -16,14 +16,12 @@
|
||||
import { mapState } from 'vuex'
|
||||
import HeaderView from "./header";
|
||||
import FooterView from "./footer";
|
||||
import AsideView from './aside/main';
|
||||
|
||||
export default {
|
||||
name: "PcMain",
|
||||
components: {
|
||||
HeaderView,
|
||||
FooterView,
|
||||
AsideView
|
||||
FooterView
|
||||
},
|
||||
computed: {
|
||||
...mapState('global', [])
|
||||
|
22
config/api.config.js
Normal file
22
config/api.config.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { NODE_ENV } from '../environment'
|
||||
|
||||
const apisMap = {
|
||||
development: {
|
||||
FE: 'http://localhost:3000',
|
||||
BASE: 'http://localhost:8099/vertical-console',
|
||||
CDN: '',
|
||||
PROXY: '/proxy',
|
||||
SOCKET: 'http://localhost:3000',
|
||||
GRAVATAR: '/proxy/static.rymcu.com/avatar'
|
||||
},
|
||||
production: {
|
||||
FE: 'https://rymcu.com',
|
||||
BASE: 'https://api.rymcu.com',
|
||||
CDN: 'https://cdn.rymcu.com',
|
||||
PROXY: 'https://cdn.rymcu.com/proxy',
|
||||
SOCKET: 'https://rymcu.com',
|
||||
GRAVATAR: 'https://static.rymcu.com/avatar'
|
||||
}
|
||||
}
|
||||
|
||||
export default apisMap[NODE_ENV]
|
36
config/app.config.js
Normal file
36
config/app.config.js
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
export const meta = {
|
||||
title: 'RYMCU - 嵌入式知识学习交流平台',
|
||||
keywords: 'RYMCU,嵌入式,51,单片机,STM,STM8,STM32',
|
||||
description: 'RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。',
|
||||
url: 'https://rymcu.com',
|
||||
author: 'rymcu',
|
||||
email: 'ronger@rymcu.com'
|
||||
}
|
||||
|
||||
export const links = {
|
||||
}
|
||||
|
||||
export const friendLinks = {
|
||||
}
|
||||
|
||||
export const music = {
|
||||
id: '638949385'
|
||||
}
|
||||
|
||||
export const fetch = {
|
||||
delay: 888
|
||||
}
|
||||
|
||||
export const color = {
|
||||
primary: '#0088f5'
|
||||
}
|
||||
|
||||
export default {
|
||||
meta,
|
||||
links,
|
||||
music,
|
||||
fetch,
|
||||
color,
|
||||
friendLinks
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
import appConfig from './config/app.config'
|
||||
import apiConfig from './config/api.config'
|
||||
import { isProdMode, isDevMode } from './environment'
|
||||
|
||||
|
||||
export default {
|
||||
/*
|
||||
@ -11,22 +15,27 @@ export default {
|
||||
render: {
|
||||
csp: true
|
||||
},
|
||||
/*
|
||||
** Environment variable configuration
|
||||
*/
|
||||
modern: true,
|
||||
dev: isDevMode,
|
||||
env: {
|
||||
baseUrl: 'http://127.0.0.1:8099'
|
||||
BASE: apiConfig.BASE,
|
||||
HOST_URL: apiConfig.SOCKET
|
||||
},
|
||||
cache: {
|
||||
max: 100,
|
||||
maxAge: 1000 * 60 * 15
|
||||
},
|
||||
/*
|
||||
** Headers of the page
|
||||
** See https://nuxtjs.org/api/configuration-head
|
||||
*/
|
||||
head: {
|
||||
title: 'RYMCU - 嵌入式知识学习交流平台',
|
||||
title: appConfig.meta.title,
|
||||
meta: [
|
||||
{ charset: 'utf-8' },
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||
{ hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
|
||||
{ hid: 'keywords', name: 'keywords', content: appConfig.meta.keywords },
|
||||
{ hid: 'description', name: 'description', content: appConfig.meta.description }
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
|
||||
@ -55,7 +64,7 @@ export default {
|
||||
** Nuxt.js modules
|
||||
*/
|
||||
modules: [
|
||||
'@nuxtjs/axios'
|
||||
['@nuxtjs/axios', { baseURL: apiConfig.BASE }]
|
||||
],
|
||||
/*
|
||||
** Build configuration
|
||||
@ -63,11 +72,5 @@ export default {
|
||||
*/
|
||||
build: {
|
||||
transpile: [/^element-ui/],
|
||||
},
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8099/vertical/',
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@ -1406,7 +1406,7 @@
|
||||
},
|
||||
"@nuxtjs/axios": {
|
||||
"version": "5.11.0",
|
||||
"resolved": "https://registry.npm.taobao.org/@nuxtjs/axios/download/@nuxtjs/axios-5.11.0.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/@nuxtjs/axios/download/@nuxtjs/axios-5.11.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40nuxtjs%2Faxios%2Fdownload%2F%40nuxtjs%2Faxios-5.11.0.tgz",
|
||||
"integrity": "sha1-J9cpemnhHDkDm5ysrGHi4NDgDx8=",
|
||||
"requires": {
|
||||
"@nuxtjs/proxy": "^2.0.0",
|
||||
@ -5102,7 +5102,7 @@
|
||||
},
|
||||
"http-proxy-middleware": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npm.taobao.org/http-proxy-middleware/download/http-proxy-middleware-1.0.4.tgz?cache=0&sync_timestamp=1589915551464&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-proxy-middleware%2Fdownload%2Fhttp-proxy-middleware-1.0.4.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/http-proxy-middleware/download/http-proxy-middleware-1.0.4.tgz",
|
||||
"integrity": "sha1-Ql6hd5hqDNo0+cgeyWHHGa22wqk=",
|
||||
"requires": {
|
||||
"@types/http-proxy": "^1.17.4",
|
||||
@ -5135,7 +5135,7 @@
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npm.taobao.org/micromatch/download/micromatch-4.0.2.tgz?cache=0&sync_timestamp=1588851826089&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmicromatch%2Fdownload%2Fmicromatch-4.0.2.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/micromatch/download/micromatch-4.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmicromatch%2Fdownload%2Fmicromatch-4.0.2.tgz",
|
||||
"integrity": "sha1-T8sJmb+fvC/L3SEvbWKbmlbDklk=",
|
||||
"requires": {
|
||||
"braces": "^3.0.1",
|
||||
@ -5531,7 +5531,7 @@
|
||||
},
|
||||
"is-retry-allowed": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npm.taobao.org/is-retry-allowed/download/is-retry-allowed-1.2.0.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/is-retry-allowed/download/is-retry-allowed-1.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-retry-allowed%2Fdownload%2Fis-retry-allowed-1.2.0.tgz",
|
||||
"integrity": "sha1-13hIi9CkZmo76KFIK58rqv7eqLQ="
|
||||
},
|
||||
"is-ssh": {
|
||||
|
@ -12,8 +12,11 @@
|
||||
"@nuxtjs/axios": "^5.11.0",
|
||||
"cross-env": "^7.0.2",
|
||||
"element-ui": "^2.13.2",
|
||||
"express": "^4.17.1",
|
||||
"nuxt": "^2.13.0",
|
||||
"vditor": "^3.3.2"
|
||||
},
|
||||
"devDependencies": {}
|
||||
"devDependencies": {
|
||||
"@nuxtjs/proxy": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,32 @@
|
||||
<template>
|
||||
<div>
|
||||
<article-list :articles="articles" @currentChange="currentChangeArticle"></article-list>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import ArticleList from '~/components/archive/list'
|
||||
export default {
|
||||
name: 'Index',
|
||||
fetch({store}) {
|
||||
return Promise.all([
|
||||
store.dispatch('article/fetchList')
|
||||
])
|
||||
},
|
||||
components: {
|
||||
ArticleList
|
||||
},
|
||||
computed: {
|
||||
articles() {
|
||||
return this.$store.state.article.list.data
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
currentChangeArticle(page) {
|
||||
this.$store.dispatch('article/fetchList', {page: page})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-header {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import apiConfig from '~/config/api.config'
|
||||
|
||||
export default function ({ app: { $axios, $cookies } }) {
|
||||
$axios.defaults.baseURL = process.env.baseUrl
|
||||
$axios.defaults.baseURL = apiConfig.BASE
|
||||
$axios.defaults.timeout = 30000
|
||||
$axios.interceptors.request.use(config => {
|
||||
config.headers['X-Token'] = $cookies.get('token') || ''
|
||||
@ -11,6 +13,16 @@ export default function ({ app: { $axios, $cookies } }) {
|
||||
if (/^[4|5]/.test(response.status)) {
|
||||
return Promise.reject(response.statusText)
|
||||
}
|
||||
let message;
|
||||
if (typeof(response.data.data) !== 'undefined') {
|
||||
message = response.data.data.message
|
||||
} else if (typeof(response.data) !== 'undefined') {
|
||||
message = response.data.message
|
||||
}
|
||||
console.log(message);
|
||||
if (response.data.success) {
|
||||
return response.data.data
|
||||
}
|
||||
return response.data
|
||||
})
|
||||
}
|
||||
|
28
server/index.js
Normal file
28
server/index.js
Normal file
@ -0,0 +1,28 @@
|
||||
const { Nuxt, Builder } = require('nuxt')
|
||||
|
||||
const app = require('express')()
|
||||
const isProd = (process.env.NODE_ENV === 'production')
|
||||
const port = process.env.PORT || 3000
|
||||
|
||||
// 用指定的配置对象实例化 Nuxt.js
|
||||
const config = require('./nuxt.config.js')
|
||||
config.dev = !isProd
|
||||
const nuxt = new Nuxt(config)
|
||||
|
||||
// 用 Nuxt.js 渲染每个路由
|
||||
app.use(nuxt.render)
|
||||
app.set("port", port)
|
||||
|
||||
// 在开发模式下启用编译构建和热加载
|
||||
if (config.dev) {
|
||||
new Builder(nuxt).build()
|
||||
.then(listen)
|
||||
} else {
|
||||
listen()
|
||||
}
|
||||
|
||||
function listen () {
|
||||
// 服务端监听
|
||||
app.listen(port, '0.0.0.0')
|
||||
console.log('Server listening on `localhost:' + port + '`.')
|
||||
}
|
@ -1,29 +1,29 @@
|
||||
import Vue from 'vue';
|
||||
import { isBrowser } from '~/environment';
|
||||
|
||||
const ARTICLE_API_PATH = 'article';
|
||||
export const ARTICLE_API_PATH = '/api/v1/console'
|
||||
|
||||
const getDefaultListData = () => {
|
||||
return {
|
||||
data: [],
|
||||
pagination: {
|
||||
total: 0,
|
||||
currentPage: 0
|
||||
articles: [],
|
||||
pagination: {}
|
||||
}
|
||||
}
|
||||
|
||||
export const state = () => {
|
||||
return {
|
||||
list: {
|
||||
fetching: false,
|
||||
data: getDefaultListData()
|
||||
},
|
||||
detail: {
|
||||
fetching: false,
|
||||
data: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
export const state = () => ({
|
||||
list: {
|
||||
fetching: false,
|
||||
data: getDefaultListData()
|
||||
},
|
||||
detail: {
|
||||
fetching: false,
|
||||
data: {}
|
||||
}
|
||||
})
|
||||
|
||||
export const mutations = () => ({
|
||||
export const mutations = {
|
||||
// 文章列表
|
||||
updateListFetching(state, action) {
|
||||
state.list.fetching = action
|
||||
@ -31,6 +31,10 @@ export const mutations = () => ({
|
||||
updateListData(state, action) {
|
||||
state.list.data = action
|
||||
},
|
||||
updateExistingListData(state, action) {
|
||||
state.list.data.data.push(...action.data)
|
||||
state.list.data.pagination = action.pagination
|
||||
},
|
||||
|
||||
// 文章详情
|
||||
updateDetailFetching(state, action) {
|
||||
@ -38,32 +42,66 @@ export const mutations = () => ({
|
||||
},
|
||||
updateDetailData(state, action) {
|
||||
state.detail.data = action
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
export const actions = () => ({
|
||||
// 更新文章阅读全文状态
|
||||
updateDetailRenderedState(state, action) {
|
||||
Vue.set(
|
||||
state.detail.data,
|
||||
'isRenderedFullContent',
|
||||
action == null ? true : action
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
// 获取文章列表
|
||||
fetchList({commit}, params = {}) {
|
||||
const isRestart = !params.page || params.page === 1
|
||||
const isLoadMore = params.page && params.page > 1
|
||||
console.log(isRestart, isLoadMore)
|
||||
|
||||
// 清空已有数据
|
||||
isRestart && commit('updateListData', getDefaultListData())
|
||||
// commit('updateListData', getDefaultListData())
|
||||
commit('updateListFetching', true)
|
||||
|
||||
return this.$axios
|
||||
.$get(ARTICLE_API_PATH, {params})
|
||||
.$get(`${ARTICLE_API_PATH}/articles`, {params})
|
||||
.then(response => {
|
||||
commit('updateListFetching', false)
|
||||
isLoadMore
|
||||
? commit('updateExistingListData', response.result)
|
||||
: commit('updateListData', response.result)
|
||||
if (isLoadMore && isBrowser) {
|
||||
commit('updateListData', response.data)
|
||||
if (isBrowser) {
|
||||
Vue.nextTick(() => {
|
||||
window.scrollTo(0, 0);
|
||||
window.scrollTo(0,0);
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(error => commit('updateListFetching', false))
|
||||
},
|
||||
|
||||
// 获取文章详情
|
||||
fetchDetail({ commit }, params = {}) {
|
||||
const delay = fetchDelay(
|
||||
isBrowser && isArticleDetailRoute(window.$nuxt.$route.name) ? null : 0
|
||||
)
|
||||
if (isBrowser) {
|
||||
Vue.nextTick(() => {
|
||||
scrollTo(0, 300, { easing: Easing['ease-in'] })
|
||||
})
|
||||
}
|
||||
commit('updateDetailFetching', true)
|
||||
commit('updateDetailData', {})
|
||||
return this.$axios
|
||||
.$get(`${ARTICLE_API_PATH}/article/${params.article_id}`)
|
||||
.then(response => {
|
||||
return new Promise(resolve => {
|
||||
delay(() => {
|
||||
commit('updateDetailData', response.result)
|
||||
commit('updateDetailFetching', false)
|
||||
resolve(response)
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch(error => {
|
||||
commit('updateDetailFetching', false)
|
||||
return Promise.reject(error)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ export const state = () => ({
|
||||
})
|
||||
|
||||
|
||||
export const getters = () => ({
|
||||
export const getters = {
|
||||
isMobile: state => state.isMobile
|
||||
})
|
||||
}
|
||||
|
||||
export const mutations = () => ({
|
||||
export const mutations = {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
export const actions = () => ({
|
||||
export const actions ={
|
||||
|
||||
})
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
export const actions = () => ({
|
||||
export const actions = {
|
||||
nuxtServerInit(store, {req}) {
|
||||
// 初始化时的全局任务
|
||||
const initFetchAppData = [
|
||||
@ -7,4 +7,4 @@ export const actions = () => ({
|
||||
]
|
||||
return Promise.all(initFetchAppData)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user