├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── .vscode └── settings.json ├── README.md ├── assets ├── README.md ├── css │ ├── lg-theme.less │ └── lg-theme │ │ ├── color.less │ │ └── var.less └── js │ ├── contest-consts.js │ ├── page-helpers.js │ └── status-mapping.js ├── components ├── README.md ├── blogs │ └── blog-item.vue ├── common │ ├── id-link.vue │ ├── page-switcher.vue │ ├── paged-list.vue │ ├── team-link.vue │ ├── user-info.vue │ └── user-link.vue ├── contests │ └── contest-item.vue ├── discuss │ └── discuss-item.vue ├── layout │ ├── app-dropdown.vue │ ├── lg-footer.vue │ ├── login-dropdown.vue │ ├── nav-bar.vue │ ├── off-canvas.vue │ └── user-dropdown.vue └── records │ ├── status-label.vue │ └── status-point.vue ├── layouts ├── README.md └── default.vue ├── middleware └── README.md ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── README.md ├── blogs │ ├── _id.vue │ └── index.vue ├── contests │ └── index.vue ├── discuss │ ├── _id.vue │ └── index.vue ├── index.vue ├── problems │ ├── _id.vue │ └── index.vue ├── records │ └── _id.vue ├── teams │ └── _id.vue └── users │ └── _id.vue ├── plugins ├── README.md ├── global-filters.js ├── lgapi.js ├── moment.js └── uikit.js ├── server.js ├── static ├── README.md └── favicon.ico └── store ├── README.md └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: 'babel-eslint', 4 | env: { 5 | browser: true, 6 | node: true 7 | }, 8 | extends: 'standard', 9 | // required to lint *.vue files 10 | plugins: [ 11 | 'vuefix', 12 | 'html' 13 | ], 14 | // add your custom rules here 15 | rules: { 16 | 'html-no-self-closing': 'off' 17 | }, 18 | globals: {} 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .nuxt 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "standard.enable": false 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Luogu Frontend 2 | 3 | ## Developer Notice 4 | 5 | I manually turned off Standard linter in `.vscode/settings.json`, because I use ESLint with Standard. A `npm i` would help you install them and configure in VSCode. 6 | 7 | ## Setup 8 | 9 | Add `127.0.0.1 f.luogu.org` to your `hosts` file, and access your local development instance. This is required to share cookies with `luogu.org`. 10 | 11 | ## Some HTML & Vue style guide 12 | 13 | 1. 2-space indent. 14 | 2. Use self-closing tags when using **components** with no inner content. Add a space before slash. 15 | eg. Use `` instead of ``, but still use ``. 16 | 3. Always use double quotes in HTML, and use single quotes in `v-bind` declarations for string literals. 17 | eg. Use ``. 18 | 4. String concating with `+` is only allowed in `v-*` declarations. Don't forget spaces before and after `+`. 19 | 5. Don't use complex expressions in `v-*` declarations. 20 | 6. Always include at least one `-` in the name of a Vue component. 21 | eg. `` 22 | 7. Always use PascalCase in imported component names. 23 | eg. `import UserDropdown from './user-dropdown'` 24 | 25 | ## Build Setup 26 | 27 | ``` bash 28 | # install dependencies 29 | $ npm install # Or yarn install 30 | 31 | # serve with hot reloading at localhost:3000 32 | $ npm run dev 33 | 34 | # build for production and launch the server 35 | $ npm run build 36 | $ npm start 37 | 38 | # generate a static project 39 | $ npm run generate 40 | ``` 41 | 42 | For detailed explanation on how things work, checkout the [Nuxt.js docs](https://nuxtjs.org). 43 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # ASSETS 2 | 3 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. 4 | 5 | More informations about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/assets#webpacked 7 | -------------------------------------------------------------------------------- /assets/css/lg-theme.less: -------------------------------------------------------------------------------- 1 | @import "~uikit/src/less/uikit.theme.less"; 2 | 3 | @import "./lg-theme/var"; 4 | @import "./lg-theme/color"; 5 | 6 | @base-body-background: #eee; 7 | 8 | @navbar-background: @lg-navbar-bg; 9 | @navbar-nav-item-height: @lg-navbar-height; 10 | @navbar-nav-item-color: @lg-navbar-color; 11 | @navbar-nav-item-hover-color: @lg-navbar-active-color; 12 | @navbar-nav-item-onclick-color: @lg-navbar-active-color; 13 | @navbar-nav-item-active-color: @lg-navbar-active-color; 14 | @navbar-item-color: @lg-navbar-color; 15 | @logo-color: @lg-navbar-active-color; 16 | @logo-hover-color: @lg-navbar-active-color; 17 | 18 | @search-color: @lg-navbar-color; 19 | @search-placeholder-color: @lg-navbar-color; 20 | @search-icon-color: @lg-navbar-color; 21 | @search-navbar-width: 200px; 22 | 23 | @global-xxlarge-font-size: 2.3rem; 24 | 25 | .hook-card() { 26 | border-radius: 10px; 27 | } 28 | 29 | .lg-float-title { 30 | padding: 0 @card-body-padding-horizontal; 31 | // Align with card. 32 | font-size: @lg-float-title-size; 33 | } 34 | 35 | @media (min-width: @breakpoint-large) { 36 | .lg-float-title { padding: 0 @card-body-padding-horizontal-l; } 37 | } 38 | 39 | .lg-largenum { 40 | font-size: 2em; 41 | } 42 | .lg-margin-reset { 43 | margin: 0; 44 | } 45 | .lg-padding-reset { 46 | padding: 0; 47 | } 48 | .lg-no-margin-bottom { margin-bottom: 0 } 49 | -------------------------------------------------------------------------------- /assets/css/lg-theme/color.less: -------------------------------------------------------------------------------- 1 | .lg-color-lblue { color: #2196f3 } 2 | .lg-bg-color-lblue { background: #2196f3 } 3 | .lg-color-dblue { color: #3f51b5 } 4 | .lg-bg-color-dblue { background: #3f51b5 } 5 | .lg-color-red { color: #f44336 } 6 | .lg-bg-color-red { background: #f44336 } 7 | .lg-color-green { color: #4caf50 } 8 | .lg-bg-color-green { background: #4caf50 } 9 | .lg-color-yellow { color: #ffeb3b } 10 | .lg-bg-color-yellow { background: #ffeb3b } 11 | -------------------------------------------------------------------------------- /assets/css/lg-theme/var.less: -------------------------------------------------------------------------------- 1 | @lg-navbar-bg: #08f; 2 | @lg-navbar-color: rgba(255,255,255,.8); 3 | @lg-navbar-active-color: #fff; 4 | @lg-navbar-height: 70px; 5 | 6 | @lg-float-title-size: 2rem; 7 | -------------------------------------------------------------------------------- /assets/js/contest-consts.js: -------------------------------------------------------------------------------- 1 | export const contestMethods = [ 2 | { /* 0, not in use */ }, 3 | { name: 'OI', color: 'red' }, // 1 4 | { name: 'ACM', color: 'red' }, // 2 5 | { name: '乐多', color: 'red' }, // 3 6 | { name: 'IOI', color: 'red' }, // 4 7 | { name: 'CF', color: 'red' }, // 5 8 | { name: '夺时', color: 'red' } // 6 9 | ] 10 | 11 | export const contestPublic = [ 12 | { /* 0, not in use */ }, 13 | { name: '官方比赛', color: 'red' }, // 1 14 | { name: '团队公开赛', color: 'red' }, // 2 15 | { name: '团队内部赛', color: 'red' }, // 3 16 | { name: '个人公开赛', color: 'red' }, // 4 17 | { name: '个人邀请赛', color: 'red' }, // 5 18 | { name: '团队邀请赛', color: 'red' }, // 6 19 | { name: '团队公开赛 (待审核)', color: 'red' }, // 7 20 | { name: '个人公开赛 (待审核)', color: 'red' } // 8 21 | ] 22 | -------------------------------------------------------------------------------- /assets/js/page-helpers.js: -------------------------------------------------------------------------------- 1 | export const setPage = hash => hash && hash.startsWith('#page-') 2 | ? parseInt(hash.split('-')[1], 10) 3 | : 1 // Defaults to 1. 4 | -------------------------------------------------------------------------------- /assets/js/status-mapping.js: -------------------------------------------------------------------------------- 1 | export const RecordStatuses = { 2 | 'Accepted': { icon: 'check', color: 'green' }, 3 | 'AC': { icon: 'check', color: 'green' }, 4 | 'Waiting': { icon: 'clock', color: 'dblue' }, 5 | 'Judging': { icon: 'play-circle', color: 'lblue' }, 6 | 'Unshown': { icon: 'ban', color: 'dblue' }, 7 | 'Compile err': { icon: 'close', color: 'yellow' }, 8 | 'Unaccepted': { icon: 'close', color: 'red' }, 9 | 'WA': { icon: 'close', color: 'red' } 10 | } 11 | -------------------------------------------------------------------------------- /components/README.md: -------------------------------------------------------------------------------- 1 | # COMPONENTS 2 | 3 | The components directory contains your Vue.js Components. 4 | Nuxt.js doesn't supercharge these components. 5 | -------------------------------------------------------------------------------- /components/blogs/blog-item.vue: -------------------------------------------------------------------------------- 1 | 9 | 19 | -------------------------------------------------------------------------------- /components/common/id-link.vue: -------------------------------------------------------------------------------- 1 | 6 | 17 | -------------------------------------------------------------------------------- /components/common/page-switcher.vue: -------------------------------------------------------------------------------- 1 | 18 | 36 | -------------------------------------------------------------------------------- /components/common/paged-list.vue: -------------------------------------------------------------------------------- 1 | 13 | 35 | -------------------------------------------------------------------------------- /components/common/team-link.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | -------------------------------------------------------------------------------- /components/common/user-info.vue: -------------------------------------------------------------------------------- 1 | 16 | 23 | 29 | -------------------------------------------------------------------------------- /components/common/user-link.vue: -------------------------------------------------------------------------------- 1 | 8 | 15 | -------------------------------------------------------------------------------- /components/contests/contest-item.vue: -------------------------------------------------------------------------------- 1 | 50 | 71 | 72 | 90 | -------------------------------------------------------------------------------- /components/discuss/discuss-item.vue: -------------------------------------------------------------------------------- 1 | 9 | 19 | -------------------------------------------------------------------------------- /components/layout/app-dropdown.vue: -------------------------------------------------------------------------------- 1 | 18 | 25 | 30 | -------------------------------------------------------------------------------- /components/layout/lg-footer.vue: -------------------------------------------------------------------------------- 1 | 28 | 37 | -------------------------------------------------------------------------------- /components/layout/login-dropdown.vue: -------------------------------------------------------------------------------- 1 | 29 | 47 | -------------------------------------------------------------------------------- /components/layout/nav-bar.vue: -------------------------------------------------------------------------------- 1 | 53 | 56 | 75 | -------------------------------------------------------------------------------- /components/layout/off-canvas.vue: -------------------------------------------------------------------------------- 1 | 44 | 51 | -------------------------------------------------------------------------------- /components/layout/user-dropdown.vue: -------------------------------------------------------------------------------- 1 | 37 | 50 | -------------------------------------------------------------------------------- /components/records/status-label.vue: -------------------------------------------------------------------------------- 1 | 4 | 17 | 22 | -------------------------------------------------------------------------------- /components/records/status-point.vue: -------------------------------------------------------------------------------- 1 | 4 | 17 | 26 | -------------------------------------------------------------------------------- /layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | This directory contains your Application Layouts. 4 | 5 | More informations about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/views#layouts 7 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 29 | 30 | 49 | -------------------------------------------------------------------------------- /middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | This directory contains your Application Middleware. 4 | The middleware lets you define custom function to be ran before rendering a page or a group of pages (layouts). 5 | 6 | More informations about the usage of this directory in the documentation: 7 | https://nuxtjs.org/guide/routing#middleware 8 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /* 3 | ** Headers of the page 4 | */ 5 | head: { 6 | title: 'Luogu vNext', 7 | meta: [ 8 | { charset: 'utf-8' }, 9 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 10 | { hid: 'description', content: 'Luogu vNext' } 11 | ], 12 | script: [ 13 | // { src: '//unpkg.cnpmjs.org/jquery/dist/jquery.min.js' }, 14 | // { src: '//unpkg.cnpmjs.org/uikit/dist/js/uikit.min.js', defer: true }, 15 | // { src: '//unpkg.cnpmjs.org/uikit/dist/js/uikit-icons.min.js', defer: true } 16 | ], 17 | link: [ 18 | { rel: 'icon', type: 'image/x-icon', href: '//luogu.oss-cn-hangzhou.aliyuncs.com/images/favicon3.ico' }, 19 | { rel: 'stylesheet', href: '//unpkg.cnpmjs.org/katex/dist/katex.min.css' } 20 | ] 21 | }, 22 | /* 23 | ** Customize the progress-bar color 24 | */ 25 | loading: { color: '#3B8070' }, 26 | plugins: [ 27 | '~plugins/global-filters', 28 | { src: '~plugins/uikit', ssr: false } 29 | ], 30 | build: { 31 | analysis: { analyzerPort: 1989 }, 32 | /* 33 | ** Run ESLINT on save 34 | */ 35 | extend (config, ctx) { 36 | if (ctx.isClient) { 37 | config.module.rules.push({ 38 | enforce: 'pre', 39 | test: /\.(js|vue)$/, 40 | loader: 'eslint-loader', 41 | exclude: /(node_modules)/ 42 | }) 43 | } 44 | }, 45 | vendor: ['axios', 'lodash', 'vue-markdown', '~plugins/lgapi'] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "luoguf", 3 | "version": "1.0.0", 4 | "description": "Luogu Frontend", 5 | "author": "laosb", 6 | "private": true, 7 | "dependencies": { 8 | "axios": "^0.16.2", 9 | "body-parser": "^1.17.2", 10 | "browser-cookies": "^1.1.0", 11 | "cookies": "^0.7.0", 12 | "jquery": "^3.2.1", 13 | "moment": "^2.18.1", 14 | "nuxt": "^1.0.0-rc3", 15 | "uikit": "^3.0.0-beta.28", 16 | "vue-markdown": "^2.2.4" 17 | }, 18 | "scripts": { 19 | "dev": "HOST=0.0.0.0 PORT=3333 nuxt", 20 | "build": "nuxt build", 21 | "ba": "nuxt build -a && NODE_ENV=production nuxt start", 22 | "start": "cross-env NODE_ENV=production nuxt start", 23 | "generate": "nuxt generate", 24 | "lint": "eslint --ext .js,.vue --ignore-path .gitignore .", 25 | "precommit": "npm run lint" 26 | }, 27 | "devDependencies": { 28 | "babel-eslint": "^7.2.3", 29 | "cross-env": "^5.0.3", 30 | "eslint": "^4.3.0", 31 | "eslint-config-standard": "^10.2.1", 32 | "eslint-loader": "^1.9.0", 33 | "eslint-plugin-html": "^3.1.1", 34 | "eslint-plugin-import": "^2.7.0", 35 | "eslint-plugin-node": "^5.1.1", 36 | "eslint-plugin-promise": "^3.5.0", 37 | "eslint-plugin-standard": "^3.0.1", 38 | "eslint-plugin-vuefix": "^0.2.0", 39 | "less": "^2.7.2", 40 | "less-loader": "^4.0.5" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /pages/README.md: -------------------------------------------------------------------------------- 1 | # PAGES 2 | 3 | This directory contains your Application Views and Routes. 4 | The framework reads all the .vue files inside this directory and create the router of your application. 5 | 6 | More informations about the usage of this directory in the documentation: 7 | https://nuxtjs.org/guide/routing 8 | -------------------------------------------------------------------------------- /pages/blogs/_id.vue: -------------------------------------------------------------------------------- 1 | 24 | 37 | -------------------------------------------------------------------------------- /pages/blogs/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 37 | -------------------------------------------------------------------------------- /pages/contests/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 42 | -------------------------------------------------------------------------------- /pages/discuss/_id.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luogu-dev/luogu-frontend-2017/9b747191d8712b8a5e7ca38c0d83cbe612c87bd2/pages/discuss/_id.vue -------------------------------------------------------------------------------- /pages/discuss/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 37 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /pages/problems/_id.vue: -------------------------------------------------------------------------------- 1 | 99 | 111 | -------------------------------------------------------------------------------- /pages/problems/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | -------------------------------------------------------------------------------- /pages/records/_id.vue: -------------------------------------------------------------------------------- 1 | 77 | 129 | 142 | -------------------------------------------------------------------------------- /pages/teams/_id.vue: -------------------------------------------------------------------------------- 1 | 63 | 82 | -------------------------------------------------------------------------------- /pages/users/_id.vue: -------------------------------------------------------------------------------- 1 | 43 | 54 | -------------------------------------------------------------------------------- /plugins/README.md: -------------------------------------------------------------------------------- 1 | # PLUGINS 2 | 3 | This directory contains your Javascript plugins that you want to run before instantiating the root vue.js application. 4 | 5 | More informations about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/plugins 7 | -------------------------------------------------------------------------------- /plugins/global-filters.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import moment from '~plugins/moment' 3 | 4 | Vue.filter('readableDate', timestamp => moment(timestamp * 1000).calendar()) 5 | -------------------------------------------------------------------------------- /plugins/lgapi.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | // import store from '~store' 3 | 4 | let UIKit = null 5 | 6 | if (process.BROWSER_BUILD) { 7 | UIKit = require('uikit') 8 | } 9 | 10 | const request = async (method, url, data) => { 11 | axios.defaults.withCredentials = true 12 | // axios.defaults.baseURL = store.state._apiBaseURL 13 | // TODO: Maybe better error handling 14 | try { 15 | const { data: rdata } = await axios[method](url, data) 16 | if (rdata.status !== 200) throw new Error(rdata.data) 17 | return rdata.data 18 | } catch (err) { 19 | if (err) { 20 | process.BROWSER_BUILD ? UIKit.modal.alert('发生错误:' + (err.message || '系统错误')) : console.log('Error' + err) 21 | return { err } 22 | } 23 | } 24 | } 25 | 26 | const post = async (url, data) => { 27 | return request('post', url, data) 28 | } 29 | 30 | const get = async (url, data) => { 31 | return request('get', url, data) 32 | } 33 | 34 | export { post, get, request } 35 | -------------------------------------------------------------------------------- /plugins/moment.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment/moment.js' 2 | import 'moment/locale/zh-cn' 3 | 4 | moment.locale('zh-cn') 5 | 6 | export default moment 7 | -------------------------------------------------------------------------------- /plugins/uikit.js: -------------------------------------------------------------------------------- 1 | import UIkit from 'uikit' 2 | import Icons from 'uikit/dist/js/uikit-icons' 3 | 4 | // loads the Icon plugin 5 | UIkit.use(Icons) 6 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | // Deprecated. 2 | 3 | const Nuxt = require('nuxt') 4 | const bodyParser = require('body-parser') 5 | const session = require('express-session') 6 | const app = require('express')() 7 | 8 | app.use(bodyParser.json()) 9 | 10 | app.use(session({ 11 | secret: 'luoguof123456!!', 12 | resave: false, 13 | saveUninitialized: false, 14 | cookie: { maxAge: 60000 } 15 | })) 16 | 17 | app.post('/_api/login', function (req, res) { 18 | if (req.body.username === 'laosb' && req.body.password === 'test123') { 19 | req.session.authUser = { username: 'laosb' } 20 | return res.json({ username: 'laosb' }) 21 | } 22 | res.status(401).json({ error: 'Bad credentials' }) 23 | }) 24 | 25 | app.post('/_api/logout', function (req, res) { 26 | delete req.session.authUser 27 | res.json({ ok: true }) 28 | }) 29 | 30 | const isProd = process.env.NODE_ENV === 'production' 31 | const nuxt = new Nuxt({ dev: !isProd }) 32 | const promise = (isProd ? Promise.resolve() : nuxt.build()) 33 | promise.then(() => { 34 | app.use(nuxt.render) 35 | app.listen(process.env.PORT || 3000) 36 | console.log(`Server is listening on http://localhost:${process.env.PORT || 3000}`) 37 | }) 38 | .catch((error) => { 39 | console.error(error) 40 | process.exit(1) 41 | }) 42 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | # STATIC 2 | 3 | This directory contains your static files. 4 | Each file inside this directory is mapped to /. 5 | 6 | Example: /static/robots.txt is mapped as /robots.txt. 7 | 8 | More informations about the usage of this directory in the documentation: 9 | https://nuxtjs.org/guide/assets#static 10 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luogu-dev/luogu-frontend-2017/9b747191d8712b8a5e7ca38c0d83cbe612c87bd2/static/favicon.ico -------------------------------------------------------------------------------- /store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | This directory contains your Vuex Store files. 4 | Vuex Store option is implemented in the Nuxt.js framework. 5 | Creating a index.js file in this directory activate the option in the framework automatically. 6 | 7 | More informations about the usage of this directory in the documentation: 8 | https://nuxtjs.org/guide/vuex-store 9 | -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | const store = () => new Vuex.Store({ 7 | 8 | state: { 9 | _currentUser: null, 10 | _clientId: null, 11 | _apiBaseURL: 'http://api.luogu.org' 12 | }, 13 | 14 | mutations: { 15 | SET_USER: function (state, user) { 16 | state._currentUser = user 17 | }, 18 | SET_CLIENTID (state, clientId) { state._clientId = clientId }, 19 | SET_APIBASEURL (state, apiBaseURL) { state._apiBaseURL = apiBaseURL } 20 | }, 21 | 22 | actions: { 23 | async nuxtServerInit ({ commit }, { req, res }) { 24 | const Cookies = require('cookies') 25 | const cookies = new Cookies(req, res) 26 | let clientId = cookies.get('__client_id') 27 | const axios = require('axios') 28 | const { get } = require('~plugins/lgapi') 29 | if (process.env.API_GATEWAY_BASEURL) commit('SET_APIBASEURL', process.env.API_GATEWAY_BASEURL) 30 | axios.defaults.baseURL = process.env.API_GATEWAY_BASEURL || 'http://api.luogu.org' 31 | if (!clientId) { 32 | // Send a request to backend to get a clientId. 33 | try { 34 | const { data } = await axios.get('/api/authenticate/getClientId', { headers: { cookie: '' } }) 35 | clientId = data.data 36 | commit('SET_CLIENTID', clientId) 37 | console.log('got new clientId from server ', clientId) 38 | } catch (e) { 39 | if (e) console.log('Error: ', e) 40 | } 41 | // const data = { data: 'a745f02bb75fd14eefe03167e34975ecd245189a' } 42 | } else { 43 | console.log('using clientId from client', clientId) 44 | } 45 | commit('SET_CLIENTID', clientId) 46 | axios.defaults.headers.common['cookie'] = `__client_id=${clientId || ''}` 47 | const currentUser = await get('/api/user/current') 48 | if (!currentUser.err) commit('SET_USER', currentUser) 49 | } 50 | } 51 | }) 52 | 53 | export default store 54 | --------------------------------------------------------------------------------