├── web
├── .env.development
├── babel.config.js
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── assets
│ │ ├── logo.png
│ │ ├── images
│ │ │ ├── 105.jpg
│ │ │ ├── 106.jpg
│ │ │ ├── 107.jpg
│ │ │ ├── 108.jpg
│ │ │ ├── 109.jpg
│ │ │ ├── 110.jpg
│ │ │ ├── 111.jpg
│ │ │ ├── 112.jpg
│ │ │ ├── 113.jpg
│ │ │ ├── 114.jpg
│ │ │ ├── 115.jpg
│ │ │ ├── 116.jpg
│ │ │ ├── 117.jpg
│ │ │ ├── 119.jpg
│ │ │ ├── 120.jpg
│ │ │ ├── 121.jpg
│ │ │ ├── 123.jpg
│ │ │ ├── 124.jpg
│ │ │ ├── 125.jpg
│ │ │ ├── 126.jpg
│ │ │ ├── 127.jpg
│ │ │ ├── 128.jpg
│ │ │ ├── 129.jpg
│ │ │ ├── 130.jpg
│ │ │ ├── 131.jpg
│ │ │ ├── 132.jpg
│ │ │ ├── 133.jpg
│ │ │ ├── 134.jpg
│ │ │ ├── 135.jpg
│ │ │ ├── 136.jpg
│ │ │ ├── 137.jpg
│ │ │ ├── 139.jpg
│ │ │ ├── 140.jpg
│ │ │ ├── 141.jpg
│ │ │ ├── 142.jpg
│ │ │ ├── 144.jpg
│ │ │ ├── 146.jpg
│ │ │ ├── 148.jpg
│ │ │ ├── 149.jpg
│ │ │ ├── 150.jpg
│ │ │ ├── 152.jpg
│ │ │ ├── 153.jpg
│ │ │ ├── 154.jpg
│ │ │ ├── 156.jpg
│ │ │ ├── 157.jpg
│ │ │ ├── 162.jpg
│ │ │ ├── 163.jpg
│ │ │ ├── 166.jpg
│ │ │ ├── 167.jpg
│ │ │ ├── 168.jpg
│ │ │ ├── 169.jpg
│ │ │ ├── 170.jpg
│ │ │ ├── 171.jpg
│ │ │ ├── 173.jpg
│ │ │ ├── 174.jpg
│ │ │ ├── 175.jpg
│ │ │ ├── 176.jpg
│ │ │ ├── 177.jpg
│ │ │ ├── 178.jpg
│ │ │ ├── 179.jpg
│ │ │ ├── 180.jpg
│ │ │ ├── 182.jpg
│ │ │ ├── 183.jpg
│ │ │ ├── 187.jpg
│ │ │ ├── 190.jpg
│ │ │ ├── 192.jpg
│ │ │ ├── 193.jpg
│ │ │ ├── 194.jpg
│ │ │ ├── 195.jpg
│ │ │ ├── 196.jpg
│ │ │ ├── 197.jpg
│ │ │ ├── 198.jpg
│ │ │ ├── 199.jpg
│ │ │ ├── 312.jpg
│ │ │ ├── 502.jpg
│ │ │ ├── 503.jpg
│ │ │ ├── 504.jpg
│ │ │ ├── 506.jpg
│ │ │ ├── 507.jpg
│ │ │ ├── 508.jpg
│ │ │ ├── 510.jpg
│ │ │ ├── 511.jpg
│ │ │ ├── 513.jpg
│ │ │ ├── 515.jpg
│ │ │ ├── 529.jpg
│ │ │ ├── index.png
│ │ │ ├── 89517772414729.jpg
│ │ │ ├── 210794580bb9303653804bb7b482f2a4.jpeg
│ │ │ ├── b9905b35bb0afa9050d9ddbe04d82d29.jpeg
│ │ │ ├── ddc8c8922cbb694dfb73c86bb03fce22.jpeg
│ │ │ ├── 230x140.1514973379.f13b6ae0ad01c866ee2d0f9209f8297a.230x140_13634.jpg
│ │ │ ├── Q750422.1515569787.8387b4634da8cb683007d3f7dc201a2c.750x422_26024.jpg
│ │ │ ├── Q750422.1516178581.bb8a035a3fe6bd3832efa4cb1ed51cf1.750x422_27946.jpg
│ │ │ ├── 5b6ba13f79129a74a3e819b78e36b922.1558861853.a8378d195d8d586b930150e8c5199391.184x124_9550.jpg
│ │ │ ├── 0426a7913eedc8b6934b19ccd22d4ab5.1559107034.80d936e909a753faa88675dc99183337.230x140_22257.jpg
│ │ │ ├── 12dda3e41fb5e12195ae3dc94ca992d0.1559038112.a13f3c53c95bb3152e9600b7fb159e7f.230x140_61124.jpg
│ │ │ ├── 24390a97b42bfed66100cfec709fe241.1559023159.43dfa3ea75c60024421acd8b64e09261.230x140_51188.jpg
│ │ │ ├── 2f423485ab865af4456fc4afbbf4fd8a.1559121831.29be5395e224e28768b3368ae490a1ee.230x140_44058.jpg
│ │ │ ├── 33a92007b5f1069c52c8b614efe9e9df.1559134600.231e17eec641eeb9c0a0d25b3a2068f6.230x140_51128.jpg
│ │ │ ├── 478c868ed3eb872b6d34226356f35f9b.1559127538.5e36ac558b88d6dd07b01ca9a7c3cc01.230x140_69933.jpg
│ │ │ ├── 5afe19c0fd9dbc9befbd7922656d9090.1559054152.921723a8e2772484663118727fe28305.230x140_16010.jpg
│ │ │ ├── 6bd0306ccc1b1dfce02580976be979c0.1559124052.c90c88f357888bbe434ca80329a833f7.230x140_24149.jpg
│ │ │ ├── 6da9003b743b65f4c0ccd295cc484e57.1559015221.ed73a77ae43df3920a4cee55e9a228f6.230x140_18091.jpg
│ │ │ ├── 6da9003b743b65f4c0ccd295cc484e57.1559116998.82e0eaa75cff42ffae8870dd2ed4aa11.230x140_21456.jpg
│ │ │ ├── 705bb5199bd0aaa463b7f5b886c404bd.1559190890.b1b9e7faecb5d9633bb9ed7e67400def.230x140_21049.jpg
│ │ │ ├── 7acce3193127d4b71a6c2b140c22dc95.1559155614.13f8d231715d38323f144865d0dd8d3b.230x140_47886.jpg
│ │ │ ├── 934b535800b1cba8f96a5d72f72f1611.1559143480.ca548a2c0c51fed1569d5593ee2b54e7.230x140_35570.jpg
│ │ │ ├── a81dba90f3c1c99db858712aad6975a6.1559121597.dd8c9d37c6fe01b3b5c15021307f84cf.230x140_19104.jpg
│ │ │ ├── afdc514c9b4d22785c9d7e0016a4e80d.1559125999.b3259d2575226266179450a16d8beaf7.230x140_69065.jpg
│ │ │ ├── c81e728d9d4c2f636f067f89cc14862c.1535178637.9b2d4b61c17f2fb310a90e4fe7562d22.184x124_58419.jpg
│ │ │ ├── d9fbed9da256e344c1fa46bb46c34c5f.1559122468.ed6b20b904dea3ced06eda250abe14b1.230x140_47631.jpg
│ │ │ ├── dfc0e642be3044e9f018c2ad5b9216b3.1559128752.9d13aa0a57ac237dd892aa90f8f5a669.230x140_79492.png
│ │ │ ├── e9a093c027c149317fccdc2264f5553e.1559104692.a6011df2bc7b168a9b077b37b62acae7.230x140_68129.png
│ │ │ └── e9af8a8f42909657795c092eb8adc7ef.1559120014.011fbdfc21154b59a0738af2e016088f.230x140_10943.jpg
│ │ ├── iconfont
│ │ │ ├── iconfont.eot
│ │ │ ├── iconfont.ttf
│ │ │ ├── iconfont.woff
│ │ │ ├── iconfont.woff2
│ │ │ ├── iconfont.css
│ │ │ ├── iconfont.svg
│ │ │ ├── iconfont.js
│ │ │ ├── demo_index.html
│ │ │ └── demo.css
│ │ └── scss
│ │ │ ├── _variables.scss
│ │ │ └── style.scss
│ ├── views
│ │ ├── About.vue
│ │ ├── Main.vue
│ │ ├── Article.vue
│ │ ├── Home.vue
│ │ └── Hero.vue
│ ├── App.vue
│ ├── main.js
│ ├── components
│ │ ├── Card.vue
│ │ ├── ListCard.vue
│ │ └── HelloWorld.vue
│ └── router.js
├── vue.config.js
├── .gitignore
├── README.md
└── package.json
├── admin
├── .env.development
├── babel.config.js
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── assets
│ │ └── logo.png
│ ├── views
│ │ ├── About.vue
│ │ ├── Home.vue
│ │ ├── Login.vue
│ │ ├── AdminUserEdit.vue
│ │ ├── AdList.vue
│ │ ├── ArticleList.vue
│ │ ├── AdminUserList.vue
│ │ ├── CategoryList.vue
│ │ ├── CategoryEdit.vue
│ │ ├── ItemList.vue
│ │ ├── HeroList.vue
│ │ ├── ItemEdit.vue
│ │ ├── ArticleEdit.vue
│ │ ├── AdEdit.vue
│ │ ├── Main.vue
│ │ └── HeroEdit.vue
│ ├── plugins
│ │ └── element.js
│ ├── App.vue
│ ├── style.css
│ ├── main.js
│ ├── http.js
│ ├── components
│ │ └── HelloWorld.vue
│ └── router.js
├── vue.config.js
├── .gitignore
├── README.md
└── package.json
├── .DS_Store
├── server
├── web
│ ├── favicon.ico
│ ├── img
│ │ ├── index.11e71079.png
│ │ ├── logo.fc64bf07.png
│ │ ├── 210794580bb9303653804bb7b482f2a4.21079458.jpeg
│ │ └── iconfont.57364c54.svg
│ ├── js
│ │ ├── about.c1a6a646.js
│ │ ├── about.c1a6a646.js.map
│ │ └── app.606e08f8.js
│ ├── index.html
│ └── css
│ │ └── chunk-vendors.23d90689.css
├── admin
│ ├── favicon.ico
│ ├── fonts
│ │ ├── element-icons.732389de.ttf
│ │ └── element-icons.535877f5.woff
│ ├── css
│ │ └── app.67e61f29.css
│ └── index.html
├── models
│ ├── Item.js
│ ├── Ad.js
│ ├── Article.js
│ ├── AdminUser.js
│ ├── Category.js
│ └── Hero.js
├── middleware
│ ├── resource.js
│ └── auth.js
├── plugins
│ └── db.js
├── index.js
├── package.json
└── routes
│ ├── admin
│ └── index.js
│ └── web
│ └── index.js
├── LICENSE
├── .gitignore
└── README.md
/web/.env.development:
--------------------------------------------------------------------------------
1 | VUE_APP_API_URL=http://localhost:3000/web/api
--------------------------------------------------------------------------------
/admin/.env.development:
--------------------------------------------------------------------------------
1 | VUE_APP_API_URL=http://localhost:3000/admin/api
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/.DS_Store
--------------------------------------------------------------------------------
/web/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/admin/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/server/web/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/server/web/favicon.ico
--------------------------------------------------------------------------------
/web/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/public/favicon.ico
--------------------------------------------------------------------------------
/web/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/logo.png
--------------------------------------------------------------------------------
/admin/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/admin/public/favicon.ico
--------------------------------------------------------------------------------
/admin/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/admin/src/assets/logo.png
--------------------------------------------------------------------------------
/server/admin/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/server/admin/favicon.ico
--------------------------------------------------------------------------------
/web/src/assets/images/105.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/105.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/106.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/106.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/107.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/107.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/108.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/108.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/109.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/109.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/110.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/110.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/111.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/111.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/112.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/112.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/113.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/113.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/114.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/114.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/115.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/115.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/116.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/116.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/117.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/117.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/119.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/119.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/120.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/120.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/121.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/121.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/123.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/123.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/124.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/124.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/125.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/125.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/126.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/126.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/127.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/127.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/128.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/128.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/129.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/129.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/130.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/130.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/131.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/131.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/132.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/132.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/133.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/133.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/134.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/134.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/135.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/135.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/136.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/136.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/137.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/137.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/139.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/139.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/140.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/140.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/141.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/141.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/142.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/142.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/144.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/144.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/146.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/146.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/148.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/148.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/149.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/149.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/150.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/150.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/152.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/152.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/153.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/153.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/154.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/154.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/156.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/156.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/157.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/157.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/162.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/162.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/163.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/163.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/166.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/166.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/167.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/167.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/168.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/168.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/169.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/169.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/170.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/170.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/171.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/171.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/173.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/173.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/174.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/174.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/175.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/175.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/176.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/176.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/177.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/177.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/178.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/178.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/179.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/179.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/180.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/180.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/182.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/182.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/183.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/183.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/187.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/187.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/190.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/190.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/192.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/192.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/193.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/193.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/194.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/194.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/195.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/195.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/196.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/196.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/197.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/197.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/198.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/198.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/199.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/199.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/312.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/312.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/502.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/502.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/503.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/503.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/504.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/504.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/506.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/506.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/507.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/507.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/508.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/508.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/510.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/510.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/511.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/511.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/513.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/513.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/515.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/515.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/529.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/529.jpg
--------------------------------------------------------------------------------
/server/web/img/index.11e71079.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/server/web/img/index.11e71079.png
--------------------------------------------------------------------------------
/server/web/img/logo.fc64bf07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/server/web/img/logo.fc64bf07.png
--------------------------------------------------------------------------------
/web/src/assets/images/index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/index.png
--------------------------------------------------------------------------------
/web/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/admin/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/web/src/assets/iconfont/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/iconfont/iconfont.eot
--------------------------------------------------------------------------------
/web/src/assets/iconfont/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/iconfont/iconfont.ttf
--------------------------------------------------------------------------------
/web/src/assets/iconfont/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/iconfont/iconfont.woff
--------------------------------------------------------------------------------
/web/src/assets/iconfont/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/iconfont/iconfont.woff2
--------------------------------------------------------------------------------
/web/src/assets/images/89517772414729.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/89517772414729.jpg
--------------------------------------------------------------------------------
/web/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/server/admin/fonts/element-icons.732389de.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/server/admin/fonts/element-icons.732389de.ttf
--------------------------------------------------------------------------------
/server/admin/fonts/element-icons.535877f5.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/server/admin/fonts/element-icons.535877f5.woff
--------------------------------------------------------------------------------
/admin/src/plugins/element.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Element from 'element-ui'
3 | import 'element-ui/lib/theme-chalk/index.css'
4 |
5 | Vue.use(Element)
6 |
--------------------------------------------------------------------------------
/admin/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputDir: __dirname + '/../server/admin',
3 | publicPath: process.env.NODE_ENV === 'production'
4 | ? '/admin/'
5 | : '/'
6 | }
--------------------------------------------------------------------------------
/web/src/assets/images/210794580bb9303653804bb7b482f2a4.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/210794580bb9303653804bb7b482f2a4.jpeg
--------------------------------------------------------------------------------
/web/src/assets/images/b9905b35bb0afa9050d9ddbe04d82d29.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/b9905b35bb0afa9050d9ddbe04d82d29.jpeg
--------------------------------------------------------------------------------
/web/src/assets/images/ddc8c8922cbb694dfb73c86bb03fce22.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/ddc8c8922cbb694dfb73c86bb03fce22.jpeg
--------------------------------------------------------------------------------
/web/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputDir: __dirname + '/../server/web',
3 | // publicPath: process.env.NODE_ENV === 'production'
4 | // ? '/'
5 | // : '/'
6 | }
--------------------------------------------------------------------------------
/server/web/img/210794580bb9303653804bb7b482f2a4.21079458.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/server/web/img/210794580bb9303653804bb7b482f2a4.21079458.jpeg
--------------------------------------------------------------------------------
/admin/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/server/models/Item.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose')
2 |
3 | const schema = new mongoose.Schema({
4 | name: { type: String },
5 | icon: { type: String },
6 | })
7 |
8 | module.exports = mongoose.model('Item', schema)
--------------------------------------------------------------------------------
/web/src/assets/images/230x140.1514973379.f13b6ae0ad01c866ee2d0f9209f8297a.230x140_13634.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/230x140.1514973379.f13b6ae0ad01c866ee2d0f9209f8297a.230x140_13634.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/Q750422.1515569787.8387b4634da8cb683007d3f7dc201a2c.750x422_26024.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/Q750422.1515569787.8387b4634da8cb683007d3f7dc201a2c.750x422_26024.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/Q750422.1516178581.bb8a035a3fe6bd3832efa4cb1ed51cf1.750x422_27946.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/Q750422.1516178581.bb8a035a3fe6bd3832efa4cb1ed51cf1.750x422_27946.jpg
--------------------------------------------------------------------------------
/server/middleware/resource.js:
--------------------------------------------------------------------------------
1 | module.exports = options => {
2 | return async (req, res, next) => {
3 | const modelName = require('inflection').classify(req.params.resource)
4 | req.Model = require(`../models/${modelName}`)
5 | next()
6 | }
7 | }
--------------------------------------------------------------------------------
/server/plugins/db.js:
--------------------------------------------------------------------------------
1 | module.exports = app => {
2 | const mongoose = require("mongoose")
3 | mongoose.connect('mongodb://127.0.0.1:27017/node-vue-moba', {
4 | useNewUrlParser: true
5 | })
6 |
7 | require('require-all')(__dirname + '/../models')
8 | }
--------------------------------------------------------------------------------
/server/models/Ad.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose')
2 |
3 | const schema = new mongoose.Schema({
4 | name: { type: String },
5 | items: [{
6 | image: { type: String },
7 | url: { type: String },
8 | }]
9 | })
10 |
11 | module.exports = mongoose.model('Ad', schema)
--------------------------------------------------------------------------------
/web/src/assets/images/5b6ba13f79129a74a3e819b78e36b922.1558861853.a8378d195d8d586b930150e8c5199391.184x124_9550.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/5b6ba13f79129a74a3e819b78e36b922.1558861853.a8378d195d8d586b930150e8c5199391.184x124_9550.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/0426a7913eedc8b6934b19ccd22d4ab5.1559107034.80d936e909a753faa88675dc99183337.230x140_22257.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/0426a7913eedc8b6934b19ccd22d4ab5.1559107034.80d936e909a753faa88675dc99183337.230x140_22257.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/12dda3e41fb5e12195ae3dc94ca992d0.1559038112.a13f3c53c95bb3152e9600b7fb159e7f.230x140_61124.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/12dda3e41fb5e12195ae3dc94ca992d0.1559038112.a13f3c53c95bb3152e9600b7fb159e7f.230x140_61124.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/24390a97b42bfed66100cfec709fe241.1559023159.43dfa3ea75c60024421acd8b64e09261.230x140_51188.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/24390a97b42bfed66100cfec709fe241.1559023159.43dfa3ea75c60024421acd8b64e09261.230x140_51188.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/2f423485ab865af4456fc4afbbf4fd8a.1559121831.29be5395e224e28768b3368ae490a1ee.230x140_44058.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/2f423485ab865af4456fc4afbbf4fd8a.1559121831.29be5395e224e28768b3368ae490a1ee.230x140_44058.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/33a92007b5f1069c52c8b614efe9e9df.1559134600.231e17eec641eeb9c0a0d25b3a2068f6.230x140_51128.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/33a92007b5f1069c52c8b614efe9e9df.1559134600.231e17eec641eeb9c0a0d25b3a2068f6.230x140_51128.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/478c868ed3eb872b6d34226356f35f9b.1559127538.5e36ac558b88d6dd07b01ca9a7c3cc01.230x140_69933.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/478c868ed3eb872b6d34226356f35f9b.1559127538.5e36ac558b88d6dd07b01ca9a7c3cc01.230x140_69933.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/5afe19c0fd9dbc9befbd7922656d9090.1559054152.921723a8e2772484663118727fe28305.230x140_16010.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/5afe19c0fd9dbc9befbd7922656d9090.1559054152.921723a8e2772484663118727fe28305.230x140_16010.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/6bd0306ccc1b1dfce02580976be979c0.1559124052.c90c88f357888bbe434ca80329a833f7.230x140_24149.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/6bd0306ccc1b1dfce02580976be979c0.1559124052.c90c88f357888bbe434ca80329a833f7.230x140_24149.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/6da9003b743b65f4c0ccd295cc484e57.1559015221.ed73a77ae43df3920a4cee55e9a228f6.230x140_18091.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/6da9003b743b65f4c0ccd295cc484e57.1559015221.ed73a77ae43df3920a4cee55e9a228f6.230x140_18091.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/6da9003b743b65f4c0ccd295cc484e57.1559116998.82e0eaa75cff42ffae8870dd2ed4aa11.230x140_21456.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/6da9003b743b65f4c0ccd295cc484e57.1559116998.82e0eaa75cff42ffae8870dd2ed4aa11.230x140_21456.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/705bb5199bd0aaa463b7f5b886c404bd.1559190890.b1b9e7faecb5d9633bb9ed7e67400def.230x140_21049.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/705bb5199bd0aaa463b7f5b886c404bd.1559190890.b1b9e7faecb5d9633bb9ed7e67400def.230x140_21049.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/7acce3193127d4b71a6c2b140c22dc95.1559155614.13f8d231715d38323f144865d0dd8d3b.230x140_47886.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/7acce3193127d4b71a6c2b140c22dc95.1559155614.13f8d231715d38323f144865d0dd8d3b.230x140_47886.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/934b535800b1cba8f96a5d72f72f1611.1559143480.ca548a2c0c51fed1569d5593ee2b54e7.230x140_35570.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/934b535800b1cba8f96a5d72f72f1611.1559143480.ca548a2c0c51fed1569d5593ee2b54e7.230x140_35570.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/a81dba90f3c1c99db858712aad6975a6.1559121597.dd8c9d37c6fe01b3b5c15021307f84cf.230x140_19104.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/a81dba90f3c1c99db858712aad6975a6.1559121597.dd8c9d37c6fe01b3b5c15021307f84cf.230x140_19104.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/afdc514c9b4d22785c9d7e0016a4e80d.1559125999.b3259d2575226266179450a16d8beaf7.230x140_69065.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/afdc514c9b4d22785c9d7e0016a4e80d.1559125999.b3259d2575226266179450a16d8beaf7.230x140_69065.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/c81e728d9d4c2f636f067f89cc14862c.1535178637.9b2d4b61c17f2fb310a90e4fe7562d22.184x124_58419.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/c81e728d9d4c2f636f067f89cc14862c.1535178637.9b2d4b61c17f2fb310a90e4fe7562d22.184x124_58419.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/d9fbed9da256e344c1fa46bb46c34c5f.1559122468.ed6b20b904dea3ced06eda250abe14b1.230x140_47631.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/d9fbed9da256e344c1fa46bb46c34c5f.1559122468.ed6b20b904dea3ced06eda250abe14b1.230x140_47631.jpg
--------------------------------------------------------------------------------
/web/src/assets/images/dfc0e642be3044e9f018c2ad5b9216b3.1559128752.9d13aa0a57ac237dd892aa90f8f5a669.230x140_79492.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/dfc0e642be3044e9f018c2ad5b9216b3.1559128752.9d13aa0a57ac237dd892aa90f8f5a669.230x140_79492.png
--------------------------------------------------------------------------------
/web/src/assets/images/e9a093c027c149317fccdc2264f5553e.1559104692.a6011df2bc7b168a9b077b37b62acae7.230x140_68129.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/e9a093c027c149317fccdc2264f5553e.1559104692.a6011df2bc7b168a9b077b37b62acae7.230x140_68129.png
--------------------------------------------------------------------------------
/web/src/assets/images/e9af8a8f42909657795c092eb8adc7ef.1559120014.011fbdfc21154b59a0738af2e016088f.230x140_10943.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/topfullstack/node-vue-moba/HEAD/web/src/assets/images/e9af8a8f42909657795c092eb8adc7ef.1559120014.011fbdfc21154b59a0738af2e016088f.230x140_10943.jpg
--------------------------------------------------------------------------------
/admin/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/web/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/server/models/Article.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose')
2 |
3 | const schema = new mongoose.Schema({
4 | categories: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'Category' }],
5 | title: { type: String },
6 | body: { type: String },
7 | }, {
8 | timestamps: true
9 | })
10 |
11 | module.exports = mongoose.model('Article', schema)
--------------------------------------------------------------------------------
/server/models/AdminUser.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose')
2 |
3 | const schema = new mongoose.Schema({
4 | username: { type: String },
5 | password: {
6 | type: String,
7 | select: false,
8 | set(val) {
9 | return require('bcrypt').hashSync(val, 10)
10 | }
11 | },
12 | })
13 |
14 | module.exports = mongoose.model('AdminUser', schema)
--------------------------------------------------------------------------------
/admin/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
7 |
8 |
19 |
--------------------------------------------------------------------------------
/server/web/js/about.c1a6a646.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["about"],{f820:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement;t._self._c;return t._m(0)},s=[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"about"},[n("h1",[t._v("This is an about page")])])}],u=n("2877"),c={},i=Object(u["a"])(c,a,s,!1,null,null,null);e["default"]=i.exports}}]);
2 | //# sourceMappingURL=about.c1a6a646.js.map
--------------------------------------------------------------------------------
/web/README.md:
--------------------------------------------------------------------------------
1 | # web
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Run your tests
19 | ```
20 | npm run test
21 | ```
22 |
23 | ### Lints and fixes files
24 | ```
25 | npm run lint
26 | ```
27 |
28 | ### Customize configuration
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/admin/README.md:
--------------------------------------------------------------------------------
1 | # admin
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Run your tests
19 | ```
20 | npm run test
21 | ```
22 |
23 | ### Lints and fixes files
24 | ```
25 | npm run lint
26 | ```
27 |
28 | ### Customize configuration
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/server/admin/css/app.67e61f29.css:
--------------------------------------------------------------------------------
1 | body,html{margin:0;padding:0}.login-card{width:25rem;margin:5rem auto}.el-header{background-color:#b3c0d1;color:#333;line-height:60px}.el-aside{color:#333}.avatar-uploader .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload:hover{border-color:#409eff}.avatar-uploader-icon{font-size:28px;color:#8c939d;min-width:5rem;height:5rem;line-height:5rem;text-align:center}.avatar{min-width:5rem;height:5rem;display:block}
--------------------------------------------------------------------------------
/admin/src/style.css:
--------------------------------------------------------------------------------
1 | .avatar-uploader .el-upload {
2 | border: 1px dashed #d9d9d9;
3 | border-radius: 6px;
4 | cursor: pointer;
5 | position: relative;
6 | overflow: hidden;
7 | }
8 | .avatar-uploader .el-upload:hover {
9 | border-color: #409eff;
10 | }
11 | .avatar-uploader-icon {
12 | font-size: 28px;
13 | color: #8c939d;
14 | min-width: 5rem;
15 | height: 5rem;
16 | line-height: 5rem;
17 | text-align: center;
18 | }
19 | .avatar {
20 | min-width: 5rem;
21 | height: 5rem;
22 | display: block;
23 | }
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | const express = require("express")
2 |
3 | const app = express()
4 |
5 | app.set('secret', 'i2u34y12oi3u4y8')
6 |
7 | app.use(require('cors')())
8 | app.use(express.json())
9 | app.use('/', express.static(__dirname + '/web'))
10 | app.use('/admin', express.static(__dirname + '/admin'))
11 | app.use('/uploads', express.static(__dirname + '/uploads'))
12 |
13 | require('./plugins/db')(app)
14 | require('./routes/admin')(app)
15 | require('./routes/web')(app)
16 |
17 | app.listen(3000, () => {
18 | console.log('http://localhost:3000');
19 | });
--------------------------------------------------------------------------------
/server/middleware/auth.js:
--------------------------------------------------------------------------------
1 | module.exports = options => {
2 | const assert = require('http-assert')
3 | const jwt = require('jsonwebtoken')
4 | const AdminUser = require('../models/AdminUser')
5 |
6 | return async (req, res, next) => {
7 | const token = String(req.headers.authorization || '').split(' ').pop()
8 | assert(token, 401, '请先登录')
9 | const { id } = jwt.verify(token, req.app.get('secret'))
10 | assert(id, 401, '请先登录')
11 | req.user = await AdminUser.findById(id)
12 | assert(req.user, 401, '请先登录')
13 | await next()
14 | }
15 | }
--------------------------------------------------------------------------------
/server/models/Category.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose')
2 |
3 | const schema = new mongoose.Schema({
4 | name: { type: String },
5 | parent: { type: mongoose.SchemaTypes.ObjectId, ref: 'Category' },
6 | })
7 |
8 | schema.virtual('children', {
9 | localField: '_id',
10 | foreignField: 'parent',
11 | justOne: false,
12 | ref: 'Category'
13 | })
14 |
15 | schema.virtual('newsList', {
16 | localField: '_id',
17 | foreignField: 'categories',
18 | justOne: false,
19 | ref: 'Article'
20 | })
21 |
22 | module.exports = mongoose.model('Category', schema)
--------------------------------------------------------------------------------
/web/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | web
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/admin/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | admin
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/admin/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import './plugins/element.js'
4 | import router from './router'
5 |
6 | import './style.css'
7 |
8 | Vue.config.productionTip = false
9 |
10 | import http from './http'
11 | Vue.prototype.$http = http
12 |
13 | Vue.mixin({
14 | computed: {
15 | uploadUrl(){
16 | return this.$http.defaults.baseURL + '/upload'
17 | }
18 | },
19 | methods: {
20 | getAuthHeaders(){
21 | return {
22 | Authorization: `Bearer ${localStorage.token || ''}`
23 | }
24 | }
25 | }
26 | })
27 |
28 | new Vue({
29 | router,
30 | render: h => h(App)
31 | }).$mount('#app')
32 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "serve": "nodemon index.js",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "bcrypt": "^3.0.6",
15 | "cors": "^2.8.5",
16 | "express": "^5.0.0-alpha.7",
17 | "http-assert": "^1.4.1",
18 | "inflection": "^1.12.0",
19 | "jsonwebtoken": "^8.5.1",
20 | "mongoose": "^5.5.6",
21 | "multer": "^1.4.1",
22 | "multer-aliyun-oss": "^1.0.1",
23 | "require-all": "^3.0.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/web/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 |
4 | Vue.config.productionTip = false
5 |
6 | import './assets/iconfont/iconfont.css'
7 | import './assets/scss/style.scss'
8 | import router from './router'
9 |
10 | import VueAwesomeSwiper from 'vue-awesome-swiper'
11 | import 'swiper/dist/css/swiper.css'
12 | Vue.use(VueAwesomeSwiper, /* { default global options } */)
13 |
14 | import Card from './components/Card.vue'
15 | Vue.component('m-card', Card)
16 |
17 | import ListCard from './components/ListCard.vue'
18 | Vue.component('m-list-card', ListCard)
19 |
20 | import axios from 'axios'
21 | Vue.prototype.$http = axios.create({
22 | baseURL: process.env.VUE_APP_API_URL || '/web/api'
23 | // baseURL: 'http://localhost:3000/web/api'
24 | })
25 |
26 | new Vue({
27 | router,
28 | render: h => h(App)
29 | }).$mount('#app')
30 |
--------------------------------------------------------------------------------
/server/web/index.html:
--------------------------------------------------------------------------------
1 | web
--------------------------------------------------------------------------------
/server/admin/index.html:
--------------------------------------------------------------------------------
1 | admin
--------------------------------------------------------------------------------
/web/src/components/Card.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
26 |
27 |
33 |
--------------------------------------------------------------------------------
/web/src/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Main from './views/Main.vue'
4 | import Home from './views/Home.vue'
5 | import Article from './views/Article.vue'
6 | import Hero from './views/Hero.vue'
7 |
8 | Vue.use(Router)
9 |
10 | export default new Router({
11 | routes: [
12 | {
13 | path: '/',
14 | component: Main,
15 | children: [
16 | { path: '/', name: 'home', component: Home },
17 | { path: '/articles/:id', name: 'article', component: Article, props: true }
18 | ]
19 | },
20 | {path: '/heroes/:id', name: 'hero', component: Hero, props: true},
21 | {
22 | path: '/about',
23 | name: 'about',
24 | // route level code-splitting
25 | // this generates a separate chunk (about.[hash].js) for this route
26 | // which is lazy-loaded when the route is visited.
27 | component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
28 | }
29 | ]
30 | })
31 |
--------------------------------------------------------------------------------
/admin/src/http.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import Vue from 'vue'
3 | import router from './router'
4 |
5 | const http = axios.create({
6 | baseURL: process.env.VUE_APP_API_URL || '/admin/api',
7 | // baseURL: 'http://localhost:3000/admin/api'
8 | })
9 | http.interceptors.request.use(function (config) {
10 | // Do something before request is sent
11 | if (localStorage.token) {
12 | config.headers.Authorization = 'Bearer ' + localStorage.token
13 | }
14 | return config;
15 | }, function (error) {
16 | // Do something with request error
17 | return Promise.reject(error);
18 | });
19 | http.interceptors.response.use(res => {
20 | return res
21 | }, err => {
22 | if (err.response.data.message) {
23 | Vue.prototype.$message({
24 | type: 'error',
25 | message: err.response.data.message
26 | })
27 |
28 | if (err.response.status === 401) {
29 | router.push('/login')
30 | }
31 | }
32 |
33 | return Promise.reject(err)
34 | })
35 |
36 | export default http
--------------------------------------------------------------------------------
/web/src/components/ListCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
{{category.name}}
8 |
9 |
10 |
11 | active = $refs.list.swiper.realIndex">
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
35 |
36 |
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Johnny Wu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/server/models/Hero.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose')
2 |
3 | const schema = new mongoose.Schema({
4 | name: { type: String },
5 | avatar: { type: String },
6 | banner: { type: String },
7 | title: { type: String },
8 | categories: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'Category' }],
9 | scores: {
10 | difficult: { type: Number },
11 | skills: { type: Number },
12 | attack: { type: Number },
13 | survive: { type: Number },
14 | },
15 | skills: [{
16 | icon: { type: String },
17 | name: { type: String },
18 | delay: { type: String },
19 | cost: { type: String },
20 | description: { type: String },
21 | tips: { type: String },
22 | }],
23 | items1: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'Item' }],
24 | items2: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'Item' }],
25 | usageTips: { type: String },
26 | battleTips: { type: String },
27 | teamTips: { type: String },
28 | partners: [{
29 | hero: { type: mongoose.SchemaTypes.ObjectId, ref: 'Hero' },
30 | description: { type: String },
31 | }],
32 | })
33 |
34 | module.exports = mongoose.model('Hero', schema, 'heroes')
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
63 | uploads
--------------------------------------------------------------------------------
/web/src/views/Main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
9 |
10 |
11 |
12 |
13 |
14 | 首页
15 |
16 |
17 | 攻略中心
18 |
19 |
20 | 赛事中心
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
36 |
43 |
--------------------------------------------------------------------------------
/admin/src/views/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 登录
13 |
14 |
15 |
16 |
17 |
18 |
19 |
40 |
41 |
47 |
--------------------------------------------------------------------------------
/admin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "admin",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "axios": "^0.18.0",
12 | "core-js": "^2.6.5",
13 | "element-ui": "^2.4.5",
14 | "vue": "^2.6.10",
15 | "vue-router": "^3.0.3",
16 | "vue2-editor": "^2.6.6"
17 | },
18 | "devDependencies": {
19 | "@vue/cli-plugin-babel": "^3.7.0",
20 | "@vue/cli-plugin-eslint": "^3.7.0",
21 | "@vue/cli-service": "^3.7.0",
22 | "babel-eslint": "^10.0.1",
23 | "eslint": "^5.16.0",
24 | "eslint-plugin-vue": "^5.0.0",
25 | "vue-cli-plugin-element": "^1.0.1",
26 | "vue-template-compiler": "^2.5.21"
27 | },
28 | "eslintConfig": {
29 | "root": true,
30 | "env": {
31 | "node": true
32 | },
33 | "extends": [
34 | "plugin:vue/essential",
35 | "eslint:recommended"
36 | ],
37 | "rules": {},
38 | "parserOptions": {
39 | "parser": "babel-eslint"
40 | }
41 | },
42 | "postcss": {
43 | "plugins": {
44 | "autoprefixer": {}
45 | }
46 | },
47 | "browserslist": [
48 | "> 1%",
49 | "last 2 versions"
50 | ]
51 | }
52 |
--------------------------------------------------------------------------------
/web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "axios": "^0.19.0",
12 | "core-js": "^2.6.5",
13 | "dayjs": "^1.8.14",
14 | "vue": "^2.6.10",
15 | "vue-awesome-swiper": "^3.1.3",
16 | "vue-router": "^3.0.3"
17 | },
18 | "devDependencies": {
19 | "@vue/cli-plugin-babel": "^3.7.0",
20 | "@vue/cli-plugin-eslint": "^3.7.0",
21 | "@vue/cli-service": "^3.7.0",
22 | "babel-eslint": "^10.0.1",
23 | "eslint": "^5.16.0",
24 | "eslint-plugin-vue": "^5.0.0",
25 | "sass": "^1.20.1",
26 | "sass-loader": "^7.1.0",
27 | "vue-template-compiler": "^2.5.21"
28 | },
29 | "eslintConfig": {
30 | "root": true,
31 | "env": {
32 | "node": true
33 | },
34 | "extends": [
35 | "plugin:vue/essential",
36 | "eslint:recommended"
37 | ],
38 | "rules": {},
39 | "parserOptions": {
40 | "parser": "babel-eslint"
41 | }
42 | },
43 | "postcss": {
44 | "plugins": {
45 | "autoprefixer": {}
46 | }
47 | },
48 | "browserslist": [
49 | "> 1%",
50 | "last 2 versions"
51 | ]
52 | }
53 |
--------------------------------------------------------------------------------
/web/src/assets/scss/_variables.scss:
--------------------------------------------------------------------------------
1 |
2 | // colors
3 | $colors: (
4 | 'primary': #db9e3f,
5 | 'info': #4b67af,
6 | 'danger': #791a15,
7 | 'blue-1': #1f3695,
8 | 'blue': #4394e4,
9 | 'white': #fff,
10 | 'white-1': #fcfcfc,
11 | 'white-2': #eceef0,
12 | 'light': #f9f9f9,
13 | 'light-1': #d4d9de,
14 | 'grey': #999,
15 | 'grey-1': #666,
16 | 'dark-1': #343440,
17 | 'dark': #222,
18 | 'black': #000,
19 |
20 | );
21 | $border-color: map-get($colors, 'light-1');
22 | // font size
23 | $base-font-size: 1rem;
24 | $font-sizes: (
25 | xxs: 0.6154,
26 | xs: 0.7692,
27 | //10px
28 | sm: 0.9231,
29 | //12px
30 | md: 1,
31 | //13px
32 | lg: 1.0769,
33 | //14px
34 | xl: 1.2308,
35 | //16px,,,,
36 | );
37 | $flex-jc: (
38 | start: flex-start,
39 | end: flex-end,
40 | center: center,
41 | between: space-between,
42 | around: space-around,
43 | );
44 | $flex-ai: (
45 | start: flex-start,
46 | end: flex-end,
47 | center: center,
48 | stretch: stretch,
49 | );
50 | // spacing
51 | // 0-5: 0
52 | // .mt-1 => margin top .pb-2
53 | $spacing-types: (
54 | m: margin,
55 | p: padding,
56 | );
57 | $spacing-directions: (
58 | t: top,
59 | r: right,
60 | b: bottom,
61 | l: left,
62 | );
63 | $spacing-base-size: 1rem;
64 | $spacing-sizes: (
65 | 0: 0,
66 | 1: 0.25,
67 | 2: 0.5,
68 | 3: 1,
69 | 4: 1.5,
70 | 5: 3,
71 | );
--------------------------------------------------------------------------------
/server/web/js/about.c1a6a646.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/views/About.vue?b5f6","webpack:///./src/views/About.vue"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","staticClass","_v","script","component","Object","componentNormalizer","__webpack_exports__"],"mappings":"8GAAA,IAAAA,EAAA,WAA0B,IAAAC,EAAAC,KAAaC,EAAAF,EAAAG,eAA0BH,EAAAI,MAAAC,GAAwB,OAAAL,EAAAM,GAAA,IACzFC,EAAA,YAAoC,IAAAP,EAAAC,KAAaC,EAAAF,EAAAG,eAA0BE,EAAAL,EAAAI,MAAAC,IAAAH,EAAwB,OAAAG,EAAA,OAAiBG,YAAA,SAAoB,CAAAH,EAAA,MAAAL,EAAAS,GAAA,2CCAxIC,EAAA,GAKAC,EAAgBC,OAAAC,EAAA,KAAAD,CAChBF,EACEX,EACAQ,GACF,EACA,KACA,KACA,MAIeO,EAAA,WAAAH","file":"js/about.c1a6a646.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"about\"},[_c('h1',[_vm._v(\"This is an about page\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./About.vue?vue&type=template&id=1ae8a7be&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}
--------------------------------------------------------------------------------
/admin/src/views/AdminUserEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{id ? '编辑' : '新建'}}管理员
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 保存
14 |
15 |
16 |
17 |
18 |
19 |
56 |
--------------------------------------------------------------------------------
/admin/src/views/AdList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
广告位列表
4 |
5 |
6 |
7 |
8 |
9 | 编辑
14 | 删除
15 |
16 |
17 |
18 |
19 |
20 |
21 |
53 |
54 |
--------------------------------------------------------------------------------
/admin/src/views/ArticleList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
文章列表
4 |
5 |
6 |
7 |
8 |
9 | 编辑
14 | 删除
15 |
16 |
17 |
18 |
19 |
20 |
21 |
53 |
54 |
--------------------------------------------------------------------------------
/admin/src/views/AdminUserList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
管理员列表
4 |
5 |
6 |
7 |
8 |
9 | 编辑
14 | 删除
15 |
16 |
17 |
18 |
19 |
20 |
21 |
53 |
54 |
--------------------------------------------------------------------------------
/admin/src/views/CategoryList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
分类列表
4 |
5 |
6 |
7 |
8 |
9 |
10 | 编辑
15 | 删除
16 |
17 |
18 |
19 |
20 |
21 |
22 |
54 |
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台
2 | > 本项目是 [Bilibili 全栈之巅](https://space.bilibili.com/341919508) 视频教程相关源码
3 | > https://github.com/wxs77577/node-vue-moba
4 | > 持续更新中... 敬请关注
5 |
6 | ## 一、 入门
7 | 1. 项目介绍
8 | 1. 工具安装和环境搭建(nodejs,npm,mongodb)
9 | 1. 初始化项目
10 |
11 | ## 二、 管理后台
12 | 1. 基于Element UI的后台管理基础界面搭建
13 |
14 | 1. 创建分类
15 | 1. 分类列表
16 | 1. 修改分类
17 | 1. 删除分类
18 | 1. 子分类
19 |
20 | 1. **通用 CRUD 接口**
21 |
22 | 1. 装备管理
23 | 1. 图片上传 (multer)
24 |
25 | 1. 英雄管理
26 | 1. 编辑英雄 (关联,多选,el-select, multiple)
27 | 1. 技能编辑
28 |
29 | 1. 文章管理
30 | 1. 富文本编辑器 (quill)
31 |
32 | 1. 首页广告管理
33 |
34 | 1. 管理员账号管理 (bcrypt)
35 | 1. 登录页面
36 | 1. 登录接口 (jwt,jsonwebtoken)
37 | 1. 服务端登录校验
38 | 1. 客户端路由限制 (beforeEach, meta)
39 | 1. 上传文件的登录校验 (el-upload, headers)
40 |
41 | ## 三、移动端网站
42 |
43 | 1. "工具样式"概念和 SASS (SCSS)
44 | 1. 样式重置
45 | 1. 网站色彩和字体定义 (colors, text)
46 | 1. 通用flex布局样式定义 (flex)
47 | 1. 常用边距定义 (margin, padding)
48 | 1. 主页框架和顶部菜单
49 | 1. 首页顶部轮播图片 (vue swiper)
50 | 1. 使用精灵图片 (sprite)
51 | 1. 使用字体图标 (iconfont)
52 | 1. 卡片组件 (card)
53 | 1. 列表卡片组件 (list-card, nav, swiper)
54 | 1. 首页新闻资讯-数据录入(+后台bug修复)
55 | 1. 首页新闻资讯-数据接口
56 | 1. 首页新闻资讯-界面展示
57 | 1. 首页英雄列表-提取官网数据
58 | 1. 首页英雄列表-录入数据
59 | 1. 首页英雄列表-界面展示
60 | 1. 新闻详情页
61 | 1. 新闻详情页-完善
62 | 1. 英雄详情页-1-前端准备
63 | 1. 英雄详情页-2-后台编辑
64 | 1. 英雄详情页-3-前端顶部
65 | 1. 英雄详情页-4-完善
66 |
67 | ## 四、发布和部署 (阿里云)
68 |
69 | 1. 生产环境编译
70 | 1. 购买域名和服务器
71 | 1. 域名解析
72 | 1. Nginx 安装和配置
73 | 1. MongoDB数据库的安装和配置
74 | 1. git 安装、配置ssh-key
75 | 1. Node.js 安装、配置淘宝镜像
76 | 1. 拉取代码,安装pm2并启动项目
77 | 1. 配置 Nginx 的反向代理
78 | 1. 迁移本地数据到服务器 (mongodump)
79 |
80 | ## 五、进阶
81 | 1. 使用免费SSL证书启用HTTPS安全连接
82 | 1. 使用阿里云OSS云存储存放上传文件
83 |
--------------------------------------------------------------------------------
/admin/src/views/CategoryEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{id ? '编辑' : '新建'}}分类
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 保存
16 |
17 |
18 |
19 |
20 |
21 |
62 |
--------------------------------------------------------------------------------
/admin/src/views/ItemList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
物品列表
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 编辑
19 | 删除
20 |
21 |
22 |
23 |
24 |
25 |
26 |
58 |
59 |
--------------------------------------------------------------------------------
/web/src/views/Article.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{model.title}}
6 |
2019-06-19
7 |
8 |
9 |
10 |
11 |
12 | 相关资讯
13 |
14 |
15 | {{item.title}}
22 |
23 |
24 |
25 |
26 |
27 |
54 |
55 |
72 |
--------------------------------------------------------------------------------
/admin/src/views/HeroList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
英雄列表
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 编辑
20 | 删除
21 |
22 |
23 |
24 |
25 |
26 |
27 |
59 |
60 |
--------------------------------------------------------------------------------
/admin/src/views/ItemEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{id ? '编辑' : '新建'}}物品
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
20 |
21 | 保存
22 |
23 |
24 |
25 |
26 |
27 |
65 |
66 |
--------------------------------------------------------------------------------
/web/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
8 |
9 |
Installed CLI Plugins
10 |
14 |
Essential Links
15 |
22 |
Ecosystem
23 |
30 |
31 |
32 |
33 |
41 |
42 |
43 |
46 |
--------------------------------------------------------------------------------
/admin/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
8 |
9 |
Installed CLI Plugins
10 |
14 |
Essential Links
15 |
22 |
Ecosystem
23 |
30 |
31 |
32 |
33 |
41 |
42 |
43 |
59 |
--------------------------------------------------------------------------------
/admin/src/views/ArticleEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{id ? '编辑' : '新建'}}文章
4 |
5 |
6 |
7 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 保存
23 |
24 |
25 |
26 |
27 |
28 |
80 |
--------------------------------------------------------------------------------
/admin/src/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Login from './views/Login.vue'
4 | import Main from './views/Main.vue'
5 | import CategoryEdit from './views/CategoryEdit.vue'
6 | import CategoryList from './views/CategoryList.vue'
7 |
8 | import ItemEdit from './views/ItemEdit.vue'
9 | import ItemList from './views/ItemList.vue'
10 |
11 | import HeroEdit from './views/HeroEdit.vue'
12 | import HeroList from './views/HeroList.vue'
13 |
14 | import ArticleEdit from './views/ArticleEdit.vue'
15 | import ArticleList from './views/ArticleList.vue'
16 |
17 | import AdEdit from './views/AdEdit.vue'
18 | import AdList from './views/AdList.vue'
19 |
20 | import AdminUserEdit from './views/AdminUserEdit.vue'
21 | import AdminUserList from './views/AdminUserList.vue'
22 |
23 |
24 | Vue.use(Router)
25 |
26 | const router = new Router({
27 | routes: [
28 | { path: '/login', name: 'login', component: Login, meta: { isPublic: true } },
29 | {
30 | path: '/',
31 | name: 'main',
32 | component: Main,
33 | children: [
34 | { path: '/categories/create', component: CategoryEdit },
35 | { path: '/categories/edit/:id', component: CategoryEdit, props: true },
36 | { path: '/categories/list', component: CategoryList },
37 |
38 | { path: '/items/create', component: ItemEdit },
39 | { path: '/items/edit/:id', component: ItemEdit, props: true },
40 | { path: '/items/list', component: ItemList },
41 |
42 | { path: '/heroes/create', component: HeroEdit },
43 | { path: '/heroes/edit/:id', component: HeroEdit, props: true },
44 | { path: '/heroes/list', component: HeroList },
45 |
46 | { path: '/articles/create', component: ArticleEdit },
47 | { path: '/articles/edit/:id', component: ArticleEdit, props: true },
48 | { path: '/articles/list', component: ArticleList },
49 |
50 | { path: '/ads/create', component: AdEdit },
51 | { path: '/ads/edit/:id', component: AdEdit, props: true },
52 | { path: '/ads/list', component: AdList },
53 |
54 | { path: '/admin_users/create', component: AdminUserEdit },
55 | { path: '/admin_users/edit/:id', component: AdminUserEdit, props: true },
56 | { path: '/admin_users/list', component: AdminUserList },
57 |
58 | ]
59 | },
60 |
61 | ]
62 | })
63 | router.beforeEach((to, from ,next) => {
64 | if (!to.meta.isPublic && !localStorage.token) {
65 | return next('/login')
66 | }
67 | next()
68 | })
69 | export default router
--------------------------------------------------------------------------------
/admin/src/views/AdEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{id ? '编辑' : '新建'}}广告位
4 |
5 |
6 |
7 |
8 |
9 |
10 | 添加广告
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | 删除
31 |
32 |
33 |
34 |
35 |
36 | 保存
37 |
38 |
39 |
40 |
41 |
42 |
78 |
--------------------------------------------------------------------------------
/web/src/assets/iconfont/iconfont.css:
--------------------------------------------------------------------------------
1 | @font-face {font-family: "iconfont";
2 | src: url('iconfont.eot?t=1559481710521'); /* IE9 */
3 | src: url('iconfont.eot?t=1559481710521#iefix') format('embedded-opentype'), /* IE6-IE8 */
4 | url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAS8AAsAAAAACYQAAARwAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDSAqGAIUVATYCJAMYCw4ABCAFhG0HUBtDCFGULk6V7OeB7TZlMBzGJlXOPxQJYQWVcAm7ePja73fuvn37BZMGSbRBFE14IpFJDJFEKGKlE6qFxHSm4yX8n95NX7ggWrXUnLrSiSMTo3Ch1NKFTBw6N/lCJqZftQYIkAmbfa7A199rmjoeita1bwGJ4n+ptWEAwxnPBKi1a9U6+PF1PCA/jfD8XLW5gq4m0DYuCbFd3VMNIpm8LhBnZpMeRAGDnEELTXVJODJHPAJfM13x7gMP1sfHPywRSV2Rtx6dVhmh9JP8UISsXVYYaphgWnM2iMdRYQHIxGWi4wJyEguQ9mcLaQfo1pTkT+U9PD6EfAj7UNTVRUACeuhOkNTT+seriEJWdIO6l6z5JDWMxKcHRs1XCEbwFYaR+SoyqKApDbaOAl8gVkBdcLSU5U/EJplYRsp6KaHIZXi1Qo8R0CYdDo2by6Xjc9bDcXuPEkg6ym5Xy+Zm7ztG8N3qJCAltJhJBvKR1u8HSZFkyIYL8y7ZLs49H0wQci9gOH7eKkmzIZvYBKoZ8Vanc5wq09rIf7rdPkS2fLl1hVQ+b5VtpVY298GrPvNEu/qwQ33yati2CKc23Oq/vuqEI9ih0QhnXWnzc7m0TpfO9Vqz5wjYNWv2R93vqaYHirS5dKcCQ9cFmvCKeftsvrRplW3vXG/jcuvDx1sWiYgeRmMPIlDFzaOIHnt+sRENOlVDxPpBZ9cl7jgYF+aTE2aZMUdwLPvYIo24uFoZ+q7mnVJ1LEtZIGsrbzNtPupSsVoeUKKfNT9VyOMBtA5Quih2uhKgUMkF1N6OLnC4gfQoamsnLxBO1dK35TvQs2doB3AgXeLNiPRvtZ7zPCduFZNB1CWIfLxT3wpkvf47UzI9JMdvfN/ElzxlfuLssPkKaXBgXPCN3DI5qhSq3Fcsc0H/OfqvIXI4yWeEQwTcrf3Lw3aHZ47QMtk5ocR94p5o3ODjt6br5HP4pcmZCQN6eQWQAV4kLD45+V7E6oj7Cjflns/hcyLuJSefi4JJAB3oMu8poLolXv8JXwOVAnRCz9BYANIT79FN9jfiPbF6hFvhf5E0g4+AH81WoIOE4smmhCi8pcZlAWRJLBtLfstlSjxRtSbFMjFnSKeteOiQZ9CLplQjhWOEZkAoQtIwBpWmCWKmLkCtyxIUTWvQNk91fJchLCRyC3NmMAj9DkHS6w0q/R4QM/U51EZ9h6I/BG3H4XXGLlOZJRUs1nPYSNWOp8wGpplWzZzELu+PTaMb9axfbDG0mLWYw1RaijKcVuFmzDaxwzLGlM5xNEWzTBNVza6HGxsZqoVl6rGBS6njuJb81FQ66ZlSDEwTSGxhYXoczIhSazyKmQGjGW0M50gi798fZjJaIz02o++HWwtjWZgnp6RJoSxAVCmaC/UdymyLMUzScTg0t4rGYjShVMOGNSoJBqUleVE9zICToq5CrEW+VBpEF1WkdK9q2ssj0CZfvESKKnLUUaIhn+OxFrIJN4/m6xdIExv0rDG5DrMMWa43NAAA') format('woff2'),
5 | url('iconfont.woff?t=1559481710521') format('woff'),
6 | url('iconfont.ttf?t=1559481710521') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
7 | url('iconfont.svg?t=1559481710521#iconfont') format('svg'); /* iOS 4.1- */
8 | }
9 |
10 | .iconfont {
11 | font-family: "iconfont" !important;
12 | font-size: 16px;
13 | font-style: normal;
14 | -webkit-font-smoothing: antialiased;
15 | -moz-osx-font-smoothing: grayscale;
16 | }
17 |
18 | .icon-news:before {
19 | content: "\e61d";
20 | }
21 |
22 | .icon-menu:before {
23 | content: "\e504";
24 | }
25 |
26 | .icon-menu1:before {
27 | content: "\e63d";
28 | }
29 |
30 | .icon-card-hero:before {
31 | content: "\e61f";
32 | }
33 |
34 | .icon-Back:before {
35 | content: "\e511";
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/server/routes/admin/index.js:
--------------------------------------------------------------------------------
1 | module.exports = app => {
2 | const express = require('express')
3 | const assert = require('http-assert')
4 | const jwt = require('jsonwebtoken')
5 | const AdminUser = require('../../models/AdminUser')
6 | const router = express.Router({
7 | mergeParams: true
8 | })
9 |
10 | // 创建资源
11 | router.post('/', async (req, res) => {
12 | const model = await req.Model.create(req.body)
13 | res.send(model)
14 | })
15 | // 更新资源
16 | router.put('/:id', async (req, res) => {
17 | const model = await req.Model.findByIdAndUpdate(req.params.id, req.body)
18 | res.send(model)
19 | })
20 | // 删除资源
21 | router.delete('/:id', async (req, res) => {
22 | await req.Model.findByIdAndDelete(req.params.id)
23 | res.send({
24 | success: true
25 | })
26 | })
27 | // 资源列表
28 | router.get('/', async (req, res) => {
29 | const queryOptions = {}
30 | if (req.Model.modelName === 'Category') {
31 | queryOptions.populate = 'parent'
32 | }
33 | const items = await req.Model.find().setOptions(queryOptions).limit(100)
34 | res.send(items)
35 | })
36 | // 资源详情
37 | router.get('/:id', async (req, res) => {
38 | const model = await req.Model.findById(req.params.id)
39 | res.send(model)
40 | })
41 | // 登录校验中间件
42 | const authMiddleware = require('../../middleware/auth')
43 | const resourceMiddleware = require('../../middleware/resource')
44 | app.use('/admin/api/rest/:resource', authMiddleware(), resourceMiddleware(), router)
45 |
46 | const multer = require('multer')
47 | const MAO = require('multer-aliyun-oss');
48 | const upload = multer({
49 | // dest: __dirname + '/../../uploads',
50 | storage: MAO({
51 | config: {
52 | region: 'oss-cn-zhangjiakou',
53 | accessKeyId: '替换为你的真实id',
54 | accessKeySecret: '替换为你的真实secret',
55 | bucket: 'node-vue-moba'
56 | }
57 | })
58 | })
59 | app.post('/admin/api/upload', authMiddleware(), upload.single('file'), async (req, res) => {
60 | const file = req.file
61 | // file.url = `http://test.topfullstack.com/uploads/${file.filename}`
62 | res.send(file)
63 | })
64 |
65 | app.post('/admin/api/login', async (req, res) => {
66 | const { username, password } = req.body
67 | // 1.根据用户名找用户
68 |
69 | const user = await AdminUser.findOne({ username }).select('+password')
70 | assert(user, 422, '用户不存在')
71 | // 2.校验密码
72 | const isValid = require('bcrypt').compareSync(password, user.password)
73 | assert(isValid, 422, '密码错误')
74 | // 3.返回token
75 | const token = jwt.sign({ id: user._id }, app.get('secret'))
76 | res.send({ token })
77 | })
78 |
79 | // 错误处理函数
80 | app.use(async (err, req, res, next) => {
81 | // console.log(err)
82 | res.status(err.statusCode || 500).send({
83 | message: err.message
84 | })
85 | })
86 | }
--------------------------------------------------------------------------------
/admin/src/views/Main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 内容管理
8 |
9 |
10 | 物品
11 | 新建物品
12 | 物品列表
13 |
14 |
15 | 英雄
16 | 新建英雄
17 | 英雄列表
18 |
19 |
20 | 文章
21 | 新建文章
22 | 文章列表
23 |
24 |
25 |
26 |
27 |
28 | 运营管理
29 |
30 |
31 | 广告位
32 | 新建广告位
33 | 广告位列表
34 |
35 |
36 |
37 |
38 |
39 | 系统设置
40 |
41 |
42 | 分类
43 | 新建分类
44 | 分类列表
45 |
46 |
47 | 管理员
48 | 新建管理员
49 | 管理员列表
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | 查看
61 | 新增
62 | 删除
63 |
64 |
65 | 王小虎
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
88 |
89 |
--------------------------------------------------------------------------------
/web/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
25 |
26 | 收起
27 |
28 |
29 |
30 |
31 |
32 |
33 |
38 | [{{news.categoryName}}]
39 | |
40 | {{news.title}}
41 | {{news.createdAt | date}}
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
55 |
56 | {{hero.name}}
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
103 |
104 |
129 |
--------------------------------------------------------------------------------
/server/web/img/iconfont.57364c54.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
42 |
--------------------------------------------------------------------------------
/web/src/assets/iconfont/iconfont.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
42 |
--------------------------------------------------------------------------------
/web/src/assets/scss/style.scss:
--------------------------------------------------------------------------------
1 | @import './variables';
2 |
3 | // reset
4 | * {
5 | box-sizing: border-box;
6 | outline: none;
7 | }
8 | html {
9 | font-size: 13px;
10 | }
11 | body {
12 | margin: 0;
13 | font-family: Arial, Helvetica, sans-serif;
14 | line-height: 1.2em;
15 | background: #f1f1f1;
16 | -webkit-font-smoothing: antialiased;
17 | }
18 | a {
19 | color: #999;
20 | }
21 | p {
22 | line-height: 1.5em;
23 | }
24 |
25 | @each $colorKey, $color in $colors {
26 | .text-#{$colorKey} {
27 | color: $color;
28 | }
29 | .bg-#{$colorKey} {
30 | background-color: $color;
31 | }
32 | }
33 | // text align
34 | @each $var in (left, center, right) {
35 | .text-#{$var} {
36 | text-align: $var !important;
37 | }
38 | }
39 |
40 | @each $sizeKey, $size in $font-sizes {
41 | .fs-#{$sizeKey} {
42 | font-size: $size * $base-font-size;
43 | }
44 | }
45 | // text overflow
46 | .text-ellipsis {
47 | display: inline-block;
48 | overflow: hidden;
49 | text-overflow: ellipsis;
50 | white-space: nowrap;
51 | }
52 |
53 | // width, height
54 | .w-100 {
55 | width: 100%;
56 | }
57 | .h-100 {
58 | height: 100%;
59 | }
60 | // flex
61 | .d-flex {
62 | display: flex;
63 | }
64 | .flex-column {
65 | flex-direction: column;
66 | }
67 | .flex-wrap {
68 | flex-wrap: wrap;
69 | }
70 |
71 | @each $key, $value in $flex-jc {
72 | .jc-#{$key} {
73 | justify-content: $value;
74 | }
75 | }
76 |
77 | @each $key, $value in $flex-ai {
78 | .ai-#{$key} {
79 | align-items: $value;
80 | }
81 | }
82 | .flex-1 {
83 | flex: 1;
84 | }
85 | .flex-grow-1 {
86 | flex-grow: 1;
87 | }
88 |
89 | // m-0, mx-0
90 | @each $typeKey, $type in $spacing-types {
91 | // .m-1
92 | @each $sizeKey, $size in $spacing-sizes {
93 | .#{$typeKey}-#{$sizeKey} {
94 | #{$type}: $size * $spacing-base-size;
95 | }
96 | }
97 | // .mx-1 , .my-1
98 | @each $sizeKey, $size in $spacing-sizes {
99 | .#{$typeKey}x-#{$sizeKey} {
100 | #{$type}-left: $size * $spacing-base-size;
101 | #{$type}-right: $size * $spacing-base-size;
102 | }
103 | .#{$typeKey}y-#{$sizeKey} {
104 | #{$type}-top: $size * $spacing-base-size;
105 | #{$type}-bottom: $size * $spacing-base-size;
106 | }
107 | }
108 | // .mt-1
109 | @each $directionKey, $direction in $spacing-directions {
110 | @each $sizeKey, $size in $spacing-sizes {
111 | .#{$typeKey}#{$directionKey}-#{$sizeKey} {
112 | #{$type}-#{$direction}: $size * $spacing-base-size;
113 | }
114 | }
115 | }
116 | }
117 | // button
118 | .btn {
119 | border:none;
120 | border-radius: 0.1538rem;
121 | font-size: map-get($font-sizes, 'sm') * $base-font-size;
122 | padding: 0.2rem 0.6rem;
123 | &.btn-lg {
124 | display: flex;
125 | justify-content: center;
126 | align-items: center;
127 | i {
128 | color: map-get($colors, 'primary');
129 | font-weight: bold;
130 | font-size: 1.5rem;
131 | margin-right: 0.5rem;
132 | }
133 | background: map-get($colors, 'white-1');
134 | border: 1px solid map-get($colors, 'white-2');
135 | padding: 0.8rem 1rem;
136 | font-size: 1rem;
137 | }
138 | }
139 | // nav
140 | .nav {
141 | display: flex;
142 | .nav-item {
143 | border-bottom: 3px solid transparent;
144 | padding-bottom: 0.2rem;
145 | &.active {
146 | color: map-get($colors, 'primary');
147 | border-bottom-color: map-get($colors, 'primary');
148 | }
149 | }
150 | &.nav-inverse {
151 | .nav-item {
152 | color: map-get($colors, 'white');
153 | &.active {
154 | border-bottom-color: map-get($colors, 'white');
155 | }
156 | }
157 | }
158 |
159 | }
160 |
161 | // sprite
162 | .sprite {
163 | background: url(../images/index.png) no-repeat 0 0;
164 | background-size: 28.8462rem;
165 | display: inline-block;
166 | &.sprite-news {
167 | width: 1.7692rem;
168 | height: 1.5385rem;
169 | background-position: 63.546% 15.517%;
170 | }
171 | &.sprite-arrow{
172 | width: 0.7692rem;
173 | height: 0.7692rem;
174 | background-position: 38.577% 52.076%;
175 | }
176 | }
177 | // borders
178 | @each $dir in (top, right, bottom, left) {
179 | .border-#{$dir} {
180 | border-#{$dir}: 1px solid $border-color;
181 | }
182 | }
--------------------------------------------------------------------------------
/web/src/assets/iconfont/iconfont.js:
--------------------------------------------------------------------------------
1 | !function(l){var e,n='',t=(e=document.getElementsByTagName("script"))[e.length-1].getAttribute("data-injectcss");if(t&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(e){console&&console.log(e)}}!function(e){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(e,0);else{var t=function(){document.removeEventListener("DOMContentLoaded",t,!1),e()};document.addEventListener("DOMContentLoaded",t,!1)}else document.attachEvent&&(c=e,o=l.document,i=!1,(a=function(){try{o.documentElement.doScroll("left")}catch(e){return void setTimeout(a,50)}n()})(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,n())});function n(){i||(i=!0,c())}var c,o,i,a}(function(){var e,t;(e=document.createElement("div")).innerHTML=n,n=null,(t=e.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",function(e,t){t.firstChild?function(e,t){t.parentNode.insertBefore(e,t)}(e,t.firstChild):t.appendChild(e)}(t,document.body))})}(window);
--------------------------------------------------------------------------------
/web/src/views/Hero.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 | 王者荣耀
7 | 攻略站
8 |
9 |
更多英雄 >
10 |
11 |
12 |
13 |
{{model.title}}
14 |
{{model.name}}
15 |
{{model.categories.map(v => v.name).join('/')}}
16 |
17 |
18 | 难度
19 | {{model.scores.difficult}}
20 | 技能
21 | {{model.scores.skills}}
22 | 攻击
23 | {{model.scores.attack}}
24 | 生存
25 | {{model.scores.survive}}
26 |
27 |
皮肤: 2 >
28 |
29 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 英雄介绍视频
51 |
52 |
53 |
54 | 英雄介绍视频
55 |
56 |
57 |
58 |
59 |
60 |
61 |
![]()
69 |
70 |
71 |
72 |
{{currentSkill.name}}
73 |
74 | (冷却值: {{currentSkill.delay}}
75 | 消耗: {{currentSkill.cost}})
76 |
77 |
78 |
{{currentSkill.description}}
79 |
80 |
小提示: {{currentSkill.tips}}
81 |
82 |
83 |
84 |
85 |
86 | 顺风出装
87 |
88 |
89 |
![]()
90 |
{{item.name}}
91 |
92 |
93 |
94 | 逆风出装
95 |
96 |
97 |
![]()
98 |
{{item.name}}
99 |
100 |
101 |
102 |
103 | {{model.usageTips}}
104 |
105 |
106 | {{model.battleTips}}
107 |
108 |
109 | {{model.teamTips}}
110 |
111 |
112 | 最佳搭档
113 |
115 |
![]()
116 |
117 | {{item.description}}
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
158 |
159 |
204 |
--------------------------------------------------------------------------------
/admin/src/views/HeroEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{id ? '编辑' : '新建'}}英雄
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | 添加技能
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | 删除
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | 添加英雄
125 |
126 |
127 |
128 |
129 |
130 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | 删除
143 |
144 |
145 |
146 |
147 |
148 |
149 | 保存
150 |
151 |
152 |
153 |
154 |
155 |
215 |
216 |
218 |
--------------------------------------------------------------------------------
/web/src/assets/iconfont/demo_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IconFont Demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | - Unicode
22 | - Font class
23 | - Symbol
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | -
32 |
33 |
news
34 | 
35 |
36 |
37 | -
38 |
39 |
menu
40 | 
41 |
42 |
43 | -
44 |
45 |
menu
46 | 
47 |
48 |
49 | -
50 |
51 |
card-hero
52 | 
53 |
54 |
55 | -
56 |
57 |
Back
58 | 
59 |
60 |
61 |
62 |
63 |
Unicode 引用
64 |
65 |
66 |
Unicode 是字体在网页端最原始的应用方式,特点是:
67 |
68 | - 兼容性最好,支持 IE6+,及所有现代浏览器。
69 | - 支持按字体的方式去动态调整图标大小,颜色等等。
70 | - 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
71 |
72 |
73 | 注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式
74 |
75 |
Unicode 使用步骤如下:
76 |
第一步:拷贝项目下面生成的 @font-face
77 |
@font-face {
79 | font-family: 'iconfont';
80 | src: url('iconfont.eot');
81 | src: url('iconfont.eot?#iefix') format('embedded-opentype'),
82 | url('iconfont.woff2') format('woff2'),
83 | url('iconfont.woff') format('woff'),
84 | url('iconfont.ttf') format('truetype'),
85 | url('iconfont.svg#iconfont') format('svg');
86 | }
87 |
88 |
第二步:定义使用 iconfont 的样式
89 |
.iconfont {
91 | font-family: "iconfont" !important;
92 | font-size: 16px;
93 | font-style: normal;
94 | -webkit-font-smoothing: antialiased;
95 | -moz-osx-font-smoothing: grayscale;
96 | }
97 |
98 |
第三步:挑选相应图标并获取字体编码,应用于页面
99 |
100 | <span class="iconfont">3</span>
102 |
103 |
104 | "iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。
105 |
106 |
107 |
108 |
109 |
110 |
111 | -
112 |
113 |
114 | news
115 |
116 | .icon-news
117 |
118 |
119 |
120 | -
121 |
122 |
123 | menu
124 |
125 | .icon-menu
126 |
127 |
128 |
129 | -
130 |
131 |
132 | menu
133 |
134 | .icon-menu1
135 |
136 |
137 |
138 | -
139 |
140 |
141 | card-hero
142 |
143 | .icon-card-hero
144 |
145 |
146 |
147 | -
148 |
149 |
150 | Back
151 |
152 | .icon-Back
153 |
154 |
155 |
156 |
157 |
158 |
font-class 引用
159 |
160 |
161 |
font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。
162 |
与 Unicode 使用方式相比,具有如下特点:
163 |
164 | - 兼容性良好,支持 IE8+,及所有现代浏览器。
165 | - 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
166 | - 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
167 | - 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
168 |
169 |
使用步骤如下:
170 |
第一步:引入项目下面生成的 fontclass 代码:
171 |
<link rel="stylesheet" href="./iconfont.css">
172 |
173 |
第二步:挑选相应图标并获取类名,应用于页面:
174 |
<span class="iconfont icon-xxx"></span>
175 |
176 |
177 | "
178 | iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。
179 |
180 |
181 |
182 |
183 |
184 |
185 | -
186 |
189 |
news
190 | #icon-news
191 |
192 |
193 | -
194 |
197 |
menu
198 | #icon-menu
199 |
200 |
201 | -
202 |
205 |
menu
206 | #icon-menu1
207 |
208 |
209 | -
210 |
213 |
card-hero
214 | #icon-card-hero
215 |
216 |
217 | -
218 |
221 |
Back
222 | #icon-Back
223 |
224 |
225 |
226 |
227 |
Symbol 引用
228 |
229 |
230 |
这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章
231 | 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:
232 |
233 | - 支持多色图标了,不再受单色限制。
234 | - 通过一些技巧,支持像字体那样,通过
font-size, color 来调整样式。
235 | - 兼容性较差,支持 IE9+,及现代浏览器。
236 | - 浏览器渲染 SVG 的性能一般,还不如 png。
237 |
238 |
使用步骤如下:
239 |
第一步:引入项目下面生成的 symbol 代码:
240 |
<script src="./iconfont.js"></script>
241 |
242 |
第二步:加入通用 CSS 代码(引入一次就行):
243 |
<style>
244 | .icon {
245 | width: 1em;
246 | height: 1em;
247 | vertical-align: -0.15em;
248 | fill: currentColor;
249 | overflow: hidden;
250 | }
251 | </style>
252 |
253 |
第三步:挑选相应图标并获取类名,应用于页面:
254 |
<svg class="icon" aria-hidden="true">
255 | <use xlink:href="#icon-xxx"></use>
256 | </svg>
257 |
258 |
259 |
260 |
261 |
262 |
263 |
282 |
283 |
284 |
--------------------------------------------------------------------------------
/web/src/assets/iconfont/demo.css:
--------------------------------------------------------------------------------
1 | /* Logo 字体 */
2 | @font-face {
3 | font-family: "iconfont logo";
4 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
5 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
6 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
7 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
8 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
9 | }
10 |
11 | .logo {
12 | font-family: "iconfont logo";
13 | font-size: 160px;
14 | font-style: normal;
15 | -webkit-font-smoothing: antialiased;
16 | -moz-osx-font-smoothing: grayscale;
17 | }
18 |
19 | /* tabs */
20 | .nav-tabs {
21 | position: relative;
22 | }
23 |
24 | .nav-tabs .nav-more {
25 | position: absolute;
26 | right: 0;
27 | bottom: 0;
28 | height: 42px;
29 | line-height: 42px;
30 | color: #666;
31 | }
32 |
33 | #tabs {
34 | border-bottom: 1px solid #eee;
35 | }
36 |
37 | #tabs li {
38 | cursor: pointer;
39 | width: 100px;
40 | height: 40px;
41 | line-height: 40px;
42 | text-align: center;
43 | font-size: 16px;
44 | border-bottom: 2px solid transparent;
45 | position: relative;
46 | z-index: 1;
47 | margin-bottom: -1px;
48 | color: #666;
49 | }
50 |
51 |
52 | #tabs .active {
53 | border-bottom-color: #f00;
54 | color: #222;
55 | }
56 |
57 | .tab-container .content {
58 | display: none;
59 | }
60 |
61 | /* 页面布局 */
62 | .main {
63 | padding: 30px 100px;
64 | width: 960px;
65 | margin: 0 auto;
66 | }
67 |
68 | .main .logo {
69 | color: #333;
70 | text-align: left;
71 | margin-bottom: 30px;
72 | line-height: 1;
73 | height: 110px;
74 | margin-top: -50px;
75 | overflow: hidden;
76 | *zoom: 1;
77 | }
78 |
79 | .main .logo a {
80 | font-size: 160px;
81 | color: #333;
82 | }
83 |
84 | .helps {
85 | margin-top: 40px;
86 | }
87 |
88 | .helps pre {
89 | padding: 20px;
90 | margin: 10px 0;
91 | border: solid 1px #e7e1cd;
92 | background-color: #fffdef;
93 | overflow: auto;
94 | }
95 |
96 | .icon_lists {
97 | width: 100% !important;
98 | overflow: hidden;
99 | *zoom: 1;
100 | }
101 |
102 | .icon_lists li {
103 | width: 100px;
104 | margin-bottom: 10px;
105 | margin-right: 20px;
106 | text-align: center;
107 | list-style: none !important;
108 | cursor: default;
109 | }
110 |
111 | .icon_lists li .code-name {
112 | line-height: 1.2;
113 | }
114 |
115 | .icon_lists .icon {
116 | display: block;
117 | height: 100px;
118 | line-height: 100px;
119 | font-size: 42px;
120 | margin: 10px auto;
121 | color: #333;
122 | -webkit-transition: font-size 0.25s linear, width 0.25s linear;
123 | -moz-transition: font-size 0.25s linear, width 0.25s linear;
124 | transition: font-size 0.25s linear, width 0.25s linear;
125 | }
126 |
127 | .icon_lists .icon:hover {
128 | font-size: 100px;
129 | }
130 |
131 | .icon_lists .svg-icon {
132 | /* 通过设置 font-size 来改变图标大小 */
133 | width: 1em;
134 | /* 图标和文字相邻时,垂直对齐 */
135 | vertical-align: -0.15em;
136 | /* 通过设置 color 来改变 SVG 的颜色/fill */
137 | fill: currentColor;
138 | /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
139 | normalize.css 中也包含这行 */
140 | overflow: hidden;
141 | }
142 |
143 | .icon_lists li .name,
144 | .icon_lists li .code-name {
145 | color: #666;
146 | }
147 |
148 | /* markdown 样式 */
149 | .markdown {
150 | color: #666;
151 | font-size: 14px;
152 | line-height: 1.8;
153 | }
154 |
155 | .highlight {
156 | line-height: 1.5;
157 | }
158 |
159 | .markdown img {
160 | vertical-align: middle;
161 | max-width: 100%;
162 | }
163 |
164 | .markdown h1 {
165 | color: #404040;
166 | font-weight: 500;
167 | line-height: 40px;
168 | margin-bottom: 24px;
169 | }
170 |
171 | .markdown h2,
172 | .markdown h3,
173 | .markdown h4,
174 | .markdown h5,
175 | .markdown h6 {
176 | color: #404040;
177 | margin: 1.6em 0 0.6em 0;
178 | font-weight: 500;
179 | clear: both;
180 | }
181 |
182 | .markdown h1 {
183 | font-size: 28px;
184 | }
185 |
186 | .markdown h2 {
187 | font-size: 22px;
188 | }
189 |
190 | .markdown h3 {
191 | font-size: 16px;
192 | }
193 |
194 | .markdown h4 {
195 | font-size: 14px;
196 | }
197 |
198 | .markdown h5 {
199 | font-size: 12px;
200 | }
201 |
202 | .markdown h6 {
203 | font-size: 12px;
204 | }
205 |
206 | .markdown hr {
207 | height: 1px;
208 | border: 0;
209 | background: #e9e9e9;
210 | margin: 16px 0;
211 | clear: both;
212 | }
213 |
214 | .markdown p {
215 | margin: 1em 0;
216 | }
217 |
218 | .markdown>p,
219 | .markdown>blockquote,
220 | .markdown>.highlight,
221 | .markdown>ol,
222 | .markdown>ul {
223 | width: 80%;
224 | }
225 |
226 | .markdown ul>li {
227 | list-style: circle;
228 | }
229 |
230 | .markdown>ul li,
231 | .markdown blockquote ul>li {
232 | margin-left: 20px;
233 | padding-left: 4px;
234 | }
235 |
236 | .markdown>ul li p,
237 | .markdown>ol li p {
238 | margin: 0.6em 0;
239 | }
240 |
241 | .markdown ol>li {
242 | list-style: decimal;
243 | }
244 |
245 | .markdown>ol li,
246 | .markdown blockquote ol>li {
247 | margin-left: 20px;
248 | padding-left: 4px;
249 | }
250 |
251 | .markdown code {
252 | margin: 0 3px;
253 | padding: 0 5px;
254 | background: #eee;
255 | border-radius: 3px;
256 | }
257 |
258 | .markdown strong,
259 | .markdown b {
260 | font-weight: 600;
261 | }
262 |
263 | .markdown>table {
264 | border-collapse: collapse;
265 | border-spacing: 0px;
266 | empty-cells: show;
267 | border: 1px solid #e9e9e9;
268 | width: 95%;
269 | margin-bottom: 24px;
270 | }
271 |
272 | .markdown>table th {
273 | white-space: nowrap;
274 | color: #333;
275 | font-weight: 600;
276 | }
277 |
278 | .markdown>table th,
279 | .markdown>table td {
280 | border: 1px solid #e9e9e9;
281 | padding: 8px 16px;
282 | text-align: left;
283 | }
284 |
285 | .markdown>table th {
286 | background: #F7F7F7;
287 | }
288 |
289 | .markdown blockquote {
290 | font-size: 90%;
291 | color: #999;
292 | border-left: 4px solid #e9e9e9;
293 | padding-left: 0.8em;
294 | margin: 1em 0;
295 | }
296 |
297 | .markdown blockquote p {
298 | margin: 0;
299 | }
300 |
301 | .markdown .anchor {
302 | opacity: 0;
303 | transition: opacity 0.3s ease;
304 | margin-left: 8px;
305 | }
306 |
307 | .markdown .waiting {
308 | color: #ccc;
309 | }
310 |
311 | .markdown h1:hover .anchor,
312 | .markdown h2:hover .anchor,
313 | .markdown h3:hover .anchor,
314 | .markdown h4:hover .anchor,
315 | .markdown h5:hover .anchor,
316 | .markdown h6:hover .anchor {
317 | opacity: 1;
318 | display: inline-block;
319 | }
320 |
321 | .markdown>br,
322 | .markdown>p>br {
323 | clear: both;
324 | }
325 |
326 |
327 | .hljs {
328 | display: block;
329 | background: white;
330 | padding: 0.5em;
331 | color: #333333;
332 | overflow-x: auto;
333 | }
334 |
335 | .hljs-comment,
336 | .hljs-meta {
337 | color: #969896;
338 | }
339 |
340 | .hljs-string,
341 | .hljs-variable,
342 | .hljs-template-variable,
343 | .hljs-strong,
344 | .hljs-emphasis,
345 | .hljs-quote {
346 | color: #df5000;
347 | }
348 |
349 | .hljs-keyword,
350 | .hljs-selector-tag,
351 | .hljs-type {
352 | color: #a71d5d;
353 | }
354 |
355 | .hljs-literal,
356 | .hljs-symbol,
357 | .hljs-bullet,
358 | .hljs-attribute {
359 | color: #0086b3;
360 | }
361 |
362 | .hljs-section,
363 | .hljs-name {
364 | color: #63a35c;
365 | }
366 |
367 | .hljs-tag {
368 | color: #333333;
369 | }
370 |
371 | .hljs-title,
372 | .hljs-attr,
373 | .hljs-selector-id,
374 | .hljs-selector-class,
375 | .hljs-selector-attr,
376 | .hljs-selector-pseudo {
377 | color: #795da3;
378 | }
379 |
380 | .hljs-addition {
381 | color: #55a532;
382 | background-color: #eaffea;
383 | }
384 |
385 | .hljs-deletion {
386 | color: #bd2c00;
387 | background-color: #ffecec;
388 | }
389 |
390 | .hljs-link {
391 | text-decoration: underline;
392 | }
393 |
394 | /* 代码高亮 */
395 | /* PrismJS 1.15.0
396 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
397 | /**
398 | * prism.js default theme for JavaScript, CSS and HTML
399 | * Based on dabblet (http://dabblet.com)
400 | * @author Lea Verou
401 | */
402 | code[class*="language-"],
403 | pre[class*="language-"] {
404 | color: black;
405 | background: none;
406 | text-shadow: 0 1px white;
407 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
408 | text-align: left;
409 | white-space: pre;
410 | word-spacing: normal;
411 | word-break: normal;
412 | word-wrap: normal;
413 | line-height: 1.5;
414 |
415 | -moz-tab-size: 4;
416 | -o-tab-size: 4;
417 | tab-size: 4;
418 |
419 | -webkit-hyphens: none;
420 | -moz-hyphens: none;
421 | -ms-hyphens: none;
422 | hyphens: none;
423 | }
424 |
425 | pre[class*="language-"]::-moz-selection,
426 | pre[class*="language-"] ::-moz-selection,
427 | code[class*="language-"]::-moz-selection,
428 | code[class*="language-"] ::-moz-selection {
429 | text-shadow: none;
430 | background: #b3d4fc;
431 | }
432 |
433 | pre[class*="language-"]::selection,
434 | pre[class*="language-"] ::selection,
435 | code[class*="language-"]::selection,
436 | code[class*="language-"] ::selection {
437 | text-shadow: none;
438 | background: #b3d4fc;
439 | }
440 |
441 | @media print {
442 |
443 | code[class*="language-"],
444 | pre[class*="language-"] {
445 | text-shadow: none;
446 | }
447 | }
448 |
449 | /* Code blocks */
450 | pre[class*="language-"] {
451 | padding: 1em;
452 | margin: .5em 0;
453 | overflow: auto;
454 | }
455 |
456 | :not(pre)>code[class*="language-"],
457 | pre[class*="language-"] {
458 | background: #f5f2f0;
459 | }
460 |
461 | /* Inline code */
462 | :not(pre)>code[class*="language-"] {
463 | padding: .1em;
464 | border-radius: .3em;
465 | white-space: normal;
466 | }
467 |
468 | .token.comment,
469 | .token.prolog,
470 | .token.doctype,
471 | .token.cdata {
472 | color: slategray;
473 | }
474 |
475 | .token.punctuation {
476 | color: #999;
477 | }
478 |
479 | .namespace {
480 | opacity: .7;
481 | }
482 |
483 | .token.property,
484 | .token.tag,
485 | .token.boolean,
486 | .token.number,
487 | .token.constant,
488 | .token.symbol,
489 | .token.deleted {
490 | color: #905;
491 | }
492 |
493 | .token.selector,
494 | .token.attr-name,
495 | .token.string,
496 | .token.char,
497 | .token.builtin,
498 | .token.inserted {
499 | color: #690;
500 | }
501 |
502 | .token.operator,
503 | .token.entity,
504 | .token.url,
505 | .language-css .token.string,
506 | .style .token.string {
507 | color: #9a6e3a;
508 | background: hsla(0, 0%, 100%, .5);
509 | }
510 |
511 | .token.atrule,
512 | .token.attr-value,
513 | .token.keyword {
514 | color: #07a;
515 | }
516 |
517 | .token.function,
518 | .token.class-name {
519 | color: #DD4A68;
520 | }
521 |
522 | .token.regex,
523 | .token.important,
524 | .token.variable {
525 | color: #e90;
526 | }
527 |
528 | .token.important,
529 | .token.bold {
530 | font-weight: bold;
531 | }
532 |
533 | .token.italic {
534 | font-style: italic;
535 | }
536 |
537 | .token.entity {
538 | cursor: help;
539 | }
540 |
--------------------------------------------------------------------------------
/server/routes/web/index.js:
--------------------------------------------------------------------------------
1 | module.exports = app => {
2 | const router = require('express').Router()
3 | const mongoose = require('mongoose')
4 | // const Article = require('../../models/Article')
5 | const Category = mongoose.model('Category')
6 | const Article = mongoose.model('Article')
7 | const Hero = mongoose.model('Hero')
8 |
9 | // 导入新闻数据
10 | router.get('/news/init', async (req, res) => {
11 | const parent = await Category.findOne({
12 | name: '新闻分类'
13 | })
14 | const cats = await Category.find().where({
15 | parent: parent
16 | }).lean()
17 | const newsTitles = ["夏日新版本“稷下星之队”即将6月上线", "王者荣耀携手两大博物馆 走进稷下学宫", "王者大陆第一学院【稷下】档案", "跨界合作丨控油神装登场,唤醒无限护肤力量!", "像素游戏时代“老四强”重聚《魂斗罗:归来》,新版本、新英雄燃爆两周年庆", "6月11日全服不停机更新公告", "【已修复】王者大陆的端午宝藏活动页面异常问题说明", "6月7日体验服停机更新公告", "6月4日全服不停机更新公告", "关于2019年KPL春季赛总决赛 RNG.M vs eStarPro 补赛、赛果及世界冠军杯安排公告", "活力夏日活动周 王者峡谷好礼多", "王者大陆的端午宝藏活动公告", "峡谷庆端午 惊喜礼不断", "【场里场外,一起开黑】感恩礼包放送", "KPL总决赛来临之际 场里场外一起开黑/观赛活动开启!", "【6月15日 再战西安 · 2019年KPL春季赛总决赛重启公告】", "王者荣耀世界冠军杯荣耀来袭,KPL赛区选拔赛谁能突围而出?", "【关于2019年KPL春季赛总决赛门票退换及异地用户现场观赛补贴公告】", "KRKPL:还在用庄周打辅助?JY边路庄周带你越塔莽!", "世冠KPL赛区战队出征名单公布 王者,无惧挑战!"]
18 | const newsList = newsTitles.map(title => {
19 | const randomCats = cats.slice(0).sort((a, b) => Math.random() - 0.5)
20 | return {
21 | categories: randomCats.slice(0, 2),
22 | title: title
23 | }
24 | })
25 | await Article.deleteMany({})
26 | await Article.insertMany(newsList)
27 | res.send(newsList)
28 | })
29 |
30 | // 新闻列表接口
31 | router.get('/news/list', async (req, res) => {
32 | // const parent = await Category.findOne({
33 | // name: '新闻分类'
34 | // }).populate({
35 | // path: 'children',
36 | // populate: {
37 | // path: 'newsList'
38 | // }
39 | // }).lean()
40 | const parent = await Category.findOne({
41 | name: '新闻分类'
42 | })
43 | const cats = await Category.aggregate([
44 | { $match: { parent: parent._id } },
45 | {
46 | $lookup: {
47 | from: 'articles',
48 | localField: '_id',
49 | foreignField: 'categories',
50 | as: 'newsList'
51 | }
52 | },
53 | {
54 | $addFields: {
55 | newsList: { $slice: ['$newsList', 5] }
56 | }
57 | }
58 | ])
59 | const subCats = cats.map(v => v._id)
60 | cats.unshift({
61 | name: '热门',
62 | newsList: await Article.find().where({
63 | categories: { $in: subCats }
64 | }).populate('categories').limit(5).lean()
65 | })
66 |
67 | cats.map(cat => {
68 | cat.newsList.map(news => {
69 | news.categoryName = (cat.name === '热门')
70 | ? news.categories[0].name : cat.name
71 | return news
72 | })
73 | return cat
74 | })
75 | res.send(cats)
76 |
77 | })
78 |
79 | // 导入英雄数据
80 | router.get('/heroes/init', async (req, res) => {
81 | await Hero.deleteMany({})
82 | const rawData = [{ "name": "热门", "heroes": [{ "name": "后羿", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/169/169.jpg" }, { "name": "孙悟空", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/167/167.jpg" }, { "name": "铠", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/193/193.jpg" }, { "name": "鲁班七号", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/112/112.jpg" }, { "name": "亚瑟", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/166/166.jpg" }, { "name": "甄姬", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/127/127.jpg" }, { "name": "孙尚香", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/111/111.jpg" }, { "name": "典韦", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/129/129.jpg" }, { "name": "韩信", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/150/150.jpg" }, { "name": "庄周", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/113/113.jpg" }] }, { "name": "战士", "heroes": [{ "name": "赵云", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/107/107.jpg" }, { "name": "钟无艳", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/117/117.jpg" }, { "name": "吕布", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/123/123.jpg" }, { "name": "曹操", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/128/128.jpg" }, { "name": "典韦", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/129/129.jpg" }, { "name": "宫本武藏", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/130/130.jpg" }, { "name": "达摩", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/134/134.jpg" }, { "name": "老夫子", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/139/139.jpg" }, { "name": "关羽", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/140/140.jpg" }, { "name": "露娜", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/146/146.jpg" }, { "name": "花木兰", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/154/154.jpg" }, { "name": "亚瑟", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/166/166.jpg" }, { "name": "孙悟空", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/167/167.jpg" }, { "name": "刘备", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/170/170.jpg" }, { "name": "杨戬", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/178/178.jpg" }, { "name": "雅典娜", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/183/183.jpg" }, { "name": "哪吒", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/180/180.jpg" }, { "name": "铠", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/193/193.jpg" }, { "name": "狂铁", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/503/503.jpg" }, { "name": "李信", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/507/507.jpg" }, { "name": "盘古", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/529/529.jpg" }] }, { "name": "法师", "heroes": [{ "name": "小乔", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/106/106.jpg" }, { "name": "墨子", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/108/108.jpg" }, { "name": "妲己", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/109/109.jpg" }, { "name": "嬴政", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/110/110.jpg" }, { "name": "高渐离", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/115/115.jpg" }, { "name": "扁鹊", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/119/119.jpg" }, { "name": "芈月", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/121/121.jpg" }, { "name": "周瑜", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/124/124.jpg" }, { "name": "甄姬", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/127/127.jpg" }, { "name": "武则天", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/136/136.jpg" }, { "name": "貂蝉", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/141/141.jpg" }, { "name": "安琪拉", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/142/142.jpg" }, { "name": "姜子牙", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/148/148.jpg" }, { "name": "王昭君", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/152/152.jpg" }, { "name": "张良", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/156/156.jpg" }, { "name": "不知火舞", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/157/157.jpg" }, { "name": "钟馗", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/175/175.jpg" }, { "name": "诸葛亮", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/190/190.jpg" }, { "name": "干将莫邪", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/182/182.jpg" }, { "name": "女娲", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/179/179.jpg" }, { "name": "杨玉环", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/176/176.jpg" }, { "name": "弈星", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/197/197.jpg" }, { "name": "米莱狄", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/504/504.jpg" }, { "name": "沈梦溪", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/312/312.jpg" }, { "name": "上官婉儿", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/513/513.jpg" }, { "name": "嫦娥", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/515/515.jpg" }] }, { "name": "坦克", "heroes": [{ "name": "廉颇", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/105/105.jpg" }, { "name": "刘禅", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/114/114.jpg" }, { "name": "白起", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/120/120.jpg" }, { "name": "夏侯惇", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/126/126.jpg" }, { "name": "项羽", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/135/135.jpg" }, { "name": "程咬金", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/144/144.jpg" }, { "name": "刘邦", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/149/149.jpg" }, { "name": "牛魔", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/168/168.jpg" }, { "name": "张飞", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/171/171.jpg" }, { "name": "东皇太一", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/187/187.jpg" }, { "name": "苏烈", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/194/194.jpg" }, { "name": "梦奇", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/198/198.jpg" }, { "name": "孙策", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/510/510.jpg" }, { "name": "猪八戒", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/511/511.jpg" }] }, { "name": "刺客", "heroes": [{ "name": "阿轲", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/116/116.jpg" }, { "name": "李白", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/131/131.jpg" }, { "name": "韩信", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/150/150.jpg" }, { "name": "兰陵王", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/153/153.jpg" }, { "name": "娜可露露", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/162/162.jpg" }, { "name": "橘右京", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/163/163.jpg" }, { "name": "百里玄策", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/195/195.jpg" }, { "name": "裴擒虎", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/502/502.jpg" }, { "name": "元歌", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/125/125.jpg" }, { "name": "司马懿", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/137/137.jpg" }, { "name": "云中君", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/506/506.jpg" }] }, { "name": "射手", "heroes": [{ "name": "孙尚香", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/111/111.jpg" }, { "name": "鲁班七号", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/112/112.jpg" }, { "name": "马可波罗", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/132/132.jpg" }, { "name": "狄仁杰", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/133/133.jpg" }, { "name": "后羿", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/169/169.jpg" }, { "name": "李元芳", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/173/173.jpg" }, { "name": "虞姬", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/174/174.jpg" }, { "name": "成吉思汗", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/177/177.jpg" }, { "name": "黄忠", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/192/192.jpg" }, { "name": "百里守约", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/196/196.jpg" }, { "name": "公孙离", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/199/199.jpg" }, { "name": "伽罗", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/508/508.jpg" }] }, { "name": "辅助", "heroes": [{ "name": "庄周", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/113/113.jpg" }, { "name": "孙膑", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/118/118.jpg" }, { "name": "蔡文姬", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/184/184.jpg" }, { "name": "太乙真人", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/186/186.jpg" }, { "name": "大乔", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/191/191.jpg" }, { "name": "鬼谷子", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/189/189.jpg" }, { "name": "明世隐", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/501/501.jpg" }, { "name": "盾山", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/509/509.jpg" }, { "name": "瑶", "avatar": "https://game.gtimg.cn/images/yxzj/img201606/heroimg/505/505.jpg" }] }]
83 | for (let cat of rawData) {
84 | if (cat.name === '热门') {
85 | continue
86 | }
87 | // 找到当前分类在数据库中对应的数据
88 | const category = await Category.findOne({
89 | name: cat.name
90 | })
91 | cat.heroes = cat.heroes.map(hero => {
92 | hero.categories = [category]
93 | return hero
94 | })
95 | // 录入英雄
96 | await Hero.insertMany(cat.heroes)
97 | }
98 |
99 | res.send(await Hero.find())
100 | })
101 |
102 | // 英雄列表接口
103 | router.get('/heroes/list', async (req, res) => {
104 | const parent = await Category.findOne({
105 | name: '英雄分类'
106 | })
107 | const cats = await Category.aggregate([
108 | { $match: { parent: parent._id } },
109 | {
110 | $lookup: {
111 | from: 'heroes',
112 | localField: '_id',
113 | foreignField: 'categories',
114 | as: 'heroList'
115 | }
116 | }
117 | ])
118 | const subCats = cats.map(v => v._id)
119 | cats.unshift({
120 | name: '热门',
121 | heroList: await Hero.find().where({
122 | categories: { $in: subCats }
123 | }).limit(10).lean()
124 | })
125 |
126 | res.send(cats)
127 |
128 | });
129 |
130 | // 文章详情
131 | router.get('/articles/:id', async (req, res) => {
132 | const data = await Article.findById(req.params.id).lean()
133 | data.related = await Article.find().where({
134 | categories: { $in: data.categories }
135 | }).limit(2)
136 | res.send(data)
137 | })
138 |
139 | router.get('/heroes/:id', async (req, res) => {
140 | const data = await Hero
141 | .findById(req.params.id)
142 | .populate('categories items1 items2 partners.hero')
143 | .lean()
144 | res.send(data)
145 | })
146 |
147 | app.use('/web/api', router)
148 | }
--------------------------------------------------------------------------------
/server/web/js/app.606e08f8.js:
--------------------------------------------------------------------------------
1 | (function(t){function e(e){for(var a,r,c=e[0],l=e[1],o=e[2],u=0,p=[];u")])],1),a("div",{staticClass:"top",style:{"background-image":"url("+t.model.banner+")"}},[a("div",{staticClass:"info text-white p-3 h-100 d-flex flex-column jc-end"},[a("div",{staticClass:"fs-sm"},[t._v(t._s(t.model.title))]),a("h2",{staticClass:"my-2"},[t._v(t._s(t.model.name))]),a("div",{staticClass:"fs-sm"},[t._v(t._s(t.model.categories.map(function(t){return t.name}).join("/")))]),a("div",{staticClass:"d-flex jc-between pt-2"},[t.model.scores?a("div",{staticClass:"scores d-flex ai-center"},[a("span",[t._v("难度")]),a("span",{staticClass:"badge bg-primary"},[t._v(t._s(t.model.scores.difficult))]),a("span",[t._v("技能")]),a("span",{staticClass:"badge bg-blue-1"},[t._v(t._s(t.model.scores.skills))]),a("span",[t._v("攻击")]),a("span",{staticClass:"badge bg-danger"},[t._v(t._s(t.model.scores.attack))]),a("span",[t._v("生存")]),a("span",{staticClass:"badge bg-dark"},[t._v(t._s(t.model.scores.survive))])]):t._e(),a("router-link",{staticClass:"text-grey fs-sm",attrs:{to:"/",tag:"span"}},[t._v("皮肤: 2 >")])],1)])]),a("div",[t._m(1),a("swiper",[a("swiper-slide",[a("div",[a("div",{staticClass:"p-3 bg-white border-bottom"},[a("div",{staticClass:"d-flex"},[a("router-link",{staticClass:"btn btn-lg flex-1",attrs:{tag:"button",to:"/"}},[a("i",{staticClass:"iconfont icon-menu1"}),t._v("\n 英雄介绍视频\n ")]),a("router-link",{staticClass:"btn btn-lg flex-1 ml-2",attrs:{tag:"button",to:"/"}},[a("i",{staticClass:"iconfont icon-menu1"}),t._v("\n 英雄介绍视频\n ")])],1),a("div",{staticClass:"skills bg-white mt-4"},[a("div",{staticClass:"d-flex jc-around"},t._l(t.model.skills,function(e,s){return a("img",{key:e.name,staticClass:"icon",class:{active:t.currentSkillIndex===s},attrs:{src:e.icon},on:{click:function(e){t.currentSkillIndex=s}}})}),0),t.currentSkill?a("div",[a("div",{staticClass:"d-flex pt-4 pb-3"},[a("h3",{staticClass:"m-0"},[t._v(t._s(t.currentSkill.name))]),a("span",{staticClass:"text-grey-1 ml-4"},[t._v("\n (冷却值: "+t._s(t.currentSkill.delay)+"\n 消耗: "+t._s(t.currentSkill.cost)+")\n ")])]),a("p",[t._v(t._s(t.currentSkill.description))]),a("div",{staticClass:"border-bottom"}),a("p",{staticClass:"text-grey-1"},[t._v("小提示: "+t._s(t.currentSkill.tips))])]):t._e()])]),a("m-card",{staticClass:"hero-items",attrs:{plain:"",icon:"menu1",title:"出装推荐"}},[a("div",{staticClass:"fs-xl"},[t._v("顺风出装")]),a("div",{staticClass:"d-flex jc-around text-center mt-3"},t._l(t.model.items1,function(e){return a("div",{key:e.name},[a("img",{staticClass:"icon",attrs:{src:e.icon}}),a("div",{staticClass:"fs-xs"},[t._v(t._s(e.name))])])}),0),a("div",{staticClass:"border-bottom mt-3"}),a("div",{staticClass:"fs-xl mt-3"},[t._v("逆风出装")]),a("div",{staticClass:"d-flex jc-around text-center mt-3"},t._l(t.model.items2,function(e){return a("div",{key:e.name},[a("img",{staticClass:"icon",attrs:{src:e.icon}}),a("div",{staticClass:"fs-xs"},[t._v(t._s(e.name))])])}),0)]),a("m-card",{attrs:{plain:"",icon:"menu1",title:"使用技巧"}},[a("p",{staticClass:"m-0"},[t._v(t._s(t.model.usageTips))])]),a("m-card",{attrs:{plain:"",icon:"menu1",title:"对抗技巧"}},[a("p",{staticClass:"m-0"},[t._v(t._s(t.model.battleTips))])]),a("m-card",{attrs:{plain:"",icon:"menu1",title:"团战思路"}},[a("p",{staticClass:"m-0"},[t._v(t._s(t.model.teamTips))])]),a("m-card",{attrs:{plain:"",icon:"menu1",title:"英雄关系"}},[a("div",{staticClass:"fs-xl"},[t._v("最佳搭档")]),t._l(t.model.partners,function(e){return a("div",{key:e.name,staticClass:"d-flex pt-3"},[a("img",{attrs:{src:e.hero.avatar,alt:"",height:"50"}}),a("p",{staticClass:"flex-1 m-0 ml-3"},[t._v("\n "+t._s(e.description)+"\n ")])])}),a("div",{staticClass:"border-bottom mt-3"})],2)],1)]),a("swiper-slide")],1)],1)]):t._e()},q=[function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"px-2 flex-1"},[s("span",{staticClass:"text-white"},[t._v("王者荣耀")]),s("span",{staticClass:"ml-2"},[t._v("攻略站")])])},function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"bg-white px-3"},[s("div",{staticClass:"nav d-flex jc-around pt-3 pb-2 border-bottom"},[s("div",{staticClass:"nav-item active"},[s("div",{staticClass:"nav-link"},[t._v("英雄初识")])]),s("div",{staticClass:"nav-item"},[s("div",{staticClass:"nav-link"},[t._v("进阶攻略")])])])])}],L={props:{id:{required:!0}},data:function(){return{model:null,currentSkillIndex:0}},computed:{currentSkill:function(){return this.model.skills[this.currentSkillIndex]}},methods:{fetch:function(){var t=Object(g["a"])(regeneratorRuntime.mark(function t(){var e;return regeneratorRuntime.wrap(function(t){while(1)switch(t.prev=t.next){case 0:return t.next=2,this.$http.get("heroes/".concat(this.id));case 2:e=t.sent,this.model=e.data;case 4:case"end":return t.stop()}},t,this)}));function e(){return t.apply(this,arguments)}return e}()},created:function(){this.fetch()}},M=L,A=(s("6e94"),Object(r["a"])(M,T,q,!1,null,null,null)),I=A.exports;a["a"].use(u["a"]);var N=new u["a"]({routes:[{path:"/",component:_,children:[{path:"/",name:"home",component:j},{path:"/articles/:id",name:"article",component:R,props:!0}]},{path:"/heroes/:id",name:"hero",component:I,props:!0},{path:"/about",name:"about",component:function(){return s.e("about").then(s.bind(null,"f820"))}}]}),H=s("7212"),U=s.n(H),B=(s("dfa4"),function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"card bg-white p-3 mt-3"},[s("div",{staticClass:"card-header d-flex ai-center",class:{"border-bottom":!t.plain,"pb-3":!t.plain}},[s("i",{staticClass:"iconfont",class:"icon-"+t.icon}),s("div",{staticClass:"fs-xl flex-1 px-2"},[s("strong",[t._v(t._s(t.title))])]),t.plain?t._e():s("i",{staticClass:"iconfont icon-menu"})]),s("div",{staticClass:"card-body pt-3"},[t._t("default")],2)])}),D=[],J={props:{title:{type:String,required:!0},icon:{type:String,required:!0},plain:{type:Boolean}}},V=J,z=(s("e60d"),Object(r["a"])(V,B,D,!1,null,null,null)),F=z.exports,G=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("m-card",{attrs:{icon:t.icon,title:t.title}},[s("div",{staticClass:"nav jc-between"},t._l(t.categories,function(e,a){return s("div",{key:a,staticClass:"nav-item",class:{active:t.active===a},on:{click:function(e){return t.$refs.list.swiper.slideTo(a)}}},[s("div",{staticClass:"nav-link"},[t._v(t._s(e.name))])])}),0),s("div",{staticClass:"pt-3"},[s("swiper",{ref:"list",attrs:{options:{autoHeight:!0}},on:{"slide-change":function(){return t.active=t.$refs.list.swiper.realIndex}}},t._l(t.categories,function(e,a){return s("swiper-slide",{key:a},[t._t("items",null,{category:e})],2)}),1)],1)])},K=[],Q={props:{icon:{type:String,required:!0},title:{type:String,required:!0},categories:{type:Array,required:!0}},data:function(){return{active:0}}},W=Q,X=Object(r["a"])(W,G,K,!1,null,null,null),Y=X.exports,Z=s("bc3a"),tt=s.n(Z);a["a"].config.productionTip=!1,a["a"].use(U.a),a["a"].component("m-card",F),a["a"].component("m-list-card",Y),a["a"].prototype.$http=tt.a.create({baseURL:Object({NODE_ENV:"production",BASE_URL:"/"}).VUE_APP_API_URL||"/web/api"}),new a["a"]({router:N,render:function(t){return t(o)}}).$mount("#app")},"6e94":function(t,e,s){"use strict";var a=s("b07d"),i=s.n(a);i.a},"78a7":function(t,e,s){},a006:function(t,e,s){"use strict";var a=s("b2d9"),i=s.n(a);i.a},ae86:function(t,e,s){},b07d:function(t,e,s){},b2d9:function(t,e,s){},bcc9:function(t,e,s){},be35:function(t,e,s){},c5e6:function(t,e,s){t.exports=s.p+"img/210794580bb9303653804bb7b482f2a4.21079458.jpeg"},cf05:function(t,e,s){t.exports=s.p+"img/logo.fc64bf07.png"},e60d:function(t,e,s){"use strict";var a=s("ae86"),i=s.n(a);i.a}});
2 | //# sourceMappingURL=app.606e08f8.js.map
--------------------------------------------------------------------------------
/server/web/css/chunk-vendors.23d90689.css:
--------------------------------------------------------------------------------
1 | .swiper-container{margin:0 auto;position:relative;overflow:hidden;list-style:none;padding:0;z-index:1}.swiper-container-no-flexbox .swiper-slide{float:left}.swiper-container-vertical>.swiper-wrapper{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.swiper-wrapper{position:relative;width:100%;height:100%;z-index:1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;-o-transition-property:transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-box-sizing:content-box;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-transform:translateZ(0);transform:translateZ(0)}.swiper-container-multirow>.swiper-wrapper{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;width:100%;height:100%;position:relative;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;-o-transition-property:transform;transition-property:transform;transition-property:transform,-webkit-transform}.swiper-slide-invisible-blank{visibility:hidden}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-transition-property:height,-webkit-transform;transition-property:height,-webkit-transform;-o-transition-property:transform,height;transition-property:transform,height;transition-property:transform,height,-webkit-transform}.swiper-container-3d{-webkit-perspective:1200px;perspective:1200px}.swiper-container-3d .swiper-cube-shadow,.swiper-container-3d .swiper-slide,.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top,.swiper-container-3d .swiper-wrapper{-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-container-3d .swiper-slide-shadow-left{background-image:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:linear-gradient(270deg,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-right{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:linear-gradient(90deg,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-top{background-image:-webkit-gradient(linear,left bottom,left top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:linear-gradient(0deg,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-bottom{background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:linear-gradient(180deg,rgba(0,0,0,.5),transparent)}.swiper-container-wp8-horizontal,.swiper-container-wp8-horizontal>.swiper-wrapper{-ms-touch-action:pan-y;touch-action:pan-y}.swiper-container-wp8-vertical,.swiper-container-wp8-vertical>.swiper-wrapper{-ms-touch-action:pan-x;touch-action:pan-x}.swiper-button-next,.swiper-button-prev{position:absolute;top:50%;width:27px;height:44px;margin-top:-22px;z-index:10;cursor:pointer;background-size:27px 44px;background-position:50%;background-repeat:no-repeat}.swiper-button-next.swiper-button-disabled,.swiper-button-prev.swiper-button-disabled{opacity:.35;cursor:auto;pointer-events:none}.swiper-button-prev,.swiper-container-rtl .swiper-button-next{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 27 44'%3E%3Cpath d='M0 22L22 0l2.1 2.1L4.2 22l19.9 19.9L22 44 0 22z' fill='%23007aff'/%3E%3C/svg%3E");left:10px;right:auto}.swiper-button-next,.swiper-container-rtl .swiper-button-prev{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 27 44'%3E%3Cpath d='M27 22L5 44l-2.1-2.1L22.8 22 2.9 2.1 5 0l22 22z' fill='%23007aff'/%3E%3C/svg%3E");right:10px;left:auto}.swiper-button-prev.swiper-button-white,.swiper-container-rtl .swiper-button-next.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 27 44'%3E%3Cpath d='M0 22L22 0l2.1 2.1L4.2 22l19.9 19.9L22 44 0 22z' fill='%23fff'/%3E%3C/svg%3E")}.swiper-button-next.swiper-button-white,.swiper-container-rtl .swiper-button-prev.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 27 44'%3E%3Cpath d='M27 22L5 44l-2.1-2.1L22.8 22 2.9 2.1 5 0l22 22z' fill='%23fff'/%3E%3C/svg%3E")}.swiper-button-prev.swiper-button-black,.swiper-container-rtl .swiper-button-next.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 27 44'%3E%3Cpath d='M0 22L22 0l2.1 2.1L4.2 22l19.9 19.9L22 44 0 22z'/%3E%3C/svg%3E")}.swiper-button-next.swiper-button-black,.swiper-container-rtl .swiper-button-prev.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 27 44'%3E%3Cpath d='M27 22L5 44l-2.1-2.1L22.8 22 2.9 2.1 5 0l22 22z'/%3E%3C/svg%3E")}.swiper-button-lock{display:none}.swiper-pagination{position:absolute;text-align:center;-webkit-transition:opacity .3s;-o-transition:.3s opacity;transition:opacity .3s;-webkit-transform:translateZ(0);transform:translateZ(0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-container-horizontal>.swiper-pagination-bullets,.swiper-pagination-custom,.swiper-pagination-fraction{bottom:10px;left:0;width:100%}.swiper-pagination-bullets-dynamic{overflow:hidden;font-size:0}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet{-webkit-transform:scale(.33);-ms-transform:scale(.33);transform:scale(.33);position:relative}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active,.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-main{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-prev{-webkit-transform:scale(.66);-ms-transform:scale(.66);transform:scale(.66)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-prev-prev{-webkit-transform:scale(.33);-ms-transform:scale(.33);transform:scale(.33)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-next{-webkit-transform:scale(.66);-ms-transform:scale(.66);transform:scale(.66)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-next-next{-webkit-transform:scale(.33);-ms-transform:scale(.33);transform:scale(.33)}.swiper-pagination-bullet{width:8px;height:8px;display:inline-block;border-radius:100%;background:#000;opacity:.2}button.swiper-pagination-bullet{border:none;margin:0;padding:0;-webkit-box-shadow:none;box-shadow:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.swiper-pagination-clickable .swiper-pagination-bullet{cursor:pointer}.swiper-pagination-bullet-active{opacity:1;background:#007aff}.swiper-container-vertical>.swiper-pagination-bullets{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination-bullets .swiper-pagination-bullet{margin:6px 0;display:block}.swiper-container-vertical>.swiper-pagination-bullets.swiper-pagination-bullets-dynamic{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);width:8px}.swiper-container-vertical>.swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet{display:inline-block;-webkit-transition:top .2s,-webkit-transform .2s;transition:top .2s,-webkit-transform .2s;-o-transition:.2s transform,.2s top;transition:transform .2s,top .2s;transition:transform .2s,top .2s,-webkit-transform .2s}.swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet{margin:0 4px}.swiper-container-horizontal>.swiper-pagination-bullets.swiper-pagination-bullets-dynamic{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);white-space:nowrap}.swiper-container-horizontal>.swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet{-webkit-transition:left .2s,-webkit-transform .2s;transition:left .2s,-webkit-transform .2s;-o-transition:.2s transform,.2s left;transition:transform .2s,left .2s;transition:transform .2s,left .2s,-webkit-transform .2s}.swiper-container-horizontal.swiper-container-rtl>.swiper-pagination-bullets-dynamic .swiper-pagination-bullet{-webkit-transition:right .2s,-webkit-transform .2s;transition:right .2s,-webkit-transform .2s;-o-transition:.2s transform,.2s right;transition:transform .2s,right .2s;transition:transform .2s,right .2s,-webkit-transform .2s}.swiper-pagination-progressbar{background:rgba(0,0,0,.25);position:absolute}.swiper-pagination-progressbar .swiper-pagination-progressbar-fill{background:#007aff;position:absolute;left:0;top:0;width:100%;height:100%;-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0);-webkit-transform-origin:left top;-ms-transform-origin:left top;transform-origin:left top}.swiper-container-rtl .swiper-pagination-progressbar .swiper-pagination-progressbar-fill{-webkit-transform-origin:right top;-ms-transform-origin:right top;transform-origin:right top}.swiper-container-horizontal>.swiper-pagination-progressbar,.swiper-container-vertical>.swiper-pagination-progressbar.swiper-pagination-progressbar-opposite{width:100%;height:4px;left:0;top:0}.swiper-container-horizontal>.swiper-pagination-progressbar.swiper-pagination-progressbar-opposite,.swiper-container-vertical>.swiper-pagination-progressbar{width:4px;height:100%;left:0;top:0}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-progressbar.swiper-pagination-white{background:hsla(0,0%,100%,.25)}.swiper-pagination-progressbar.swiper-pagination-white .swiper-pagination-progressbar-fill{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-pagination-progressbar.swiper-pagination-black{background:rgba(0,0,0,.25)}.swiper-pagination-progressbar.swiper-pagination-black .swiper-pagination-progressbar-fill{background:#000}.swiper-pagination-lock{display:none}.swiper-scrollbar{border-radius:10px;position:relative;-ms-touch-action:none;background:rgba(0,0,0,.1)}.swiper-container-horizontal>.swiper-scrollbar{position:absolute;left:1%;bottom:3px;z-index:50;height:5px;width:98%}.swiper-container-vertical>.swiper-scrollbar{position:absolute;right:3px;top:1%;z-index:50;width:5px;height:98%}.swiper-scrollbar-drag{height:100%;width:100%;position:relative;background:rgba(0,0,0,.5);border-radius:10px;left:0;top:0}.swiper-scrollbar-cursor-drag{cursor:move}.swiper-scrollbar-lock{display:none}.swiper-zoom-container{width:100%;height:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;text-align:center}.swiper-zoom-container>canvas,.swiper-zoom-container>img,.swiper-zoom-container>svg{max-width:100%;max-height:100%;-o-object-fit:contain;object-fit:contain}.swiper-slide-zoomed{cursor:move}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;-webkit-transform-origin:50%;-ms-transform-origin:50%;transform-origin:50%;-webkit-animation:swiper-preloader-spin 1s steps(12) infinite;animation:swiper-preloader-spin 1s steps(12) infinite}.swiper-lazy-preloader:after{display:block;content:"";width:100%;height:100%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath id='a' stroke='%236c6c6c' stroke-width='11' stroke-linecap='round' d='M60 7v20'/%3E%3C/defs%3E%3Cuse xlink:href='%23a' opacity='.27'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(30 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(60 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(90 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(120 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(150 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.37' transform='rotate(180 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.46' transform='rotate(210 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.56' transform='rotate(240 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.66' transform='rotate(270 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.75' transform='rotate(300 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.85' transform='rotate(330 60 60)'/%3E%3C/svg%3E");background-position:50%;background-size:100%;background-repeat:no-repeat}.swiper-lazy-preloader-white:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3Cpath id='a' stroke='%23fff' stroke-width='11' stroke-linecap='round' d='M60 7v20'/%3E%3C/defs%3E%3Cuse xlink:href='%23a' opacity='.27'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(30 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(60 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(90 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(120 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.27' transform='rotate(150 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.37' transform='rotate(180 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.46' transform='rotate(210 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.56' transform='rotate(240 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.66' transform='rotate(270 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.75' transform='rotate(300 60 60)'/%3E%3Cuse xlink:href='%23a' opacity='.85' transform='rotate(330 60 60)'/%3E%3C/svg%3E")}@-webkit-keyframes swiper-preloader-spin{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes swiper-preloader-spin{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.swiper-container .swiper-notification{position:absolute;left:0;top:0;pointer-events:none;opacity:0;z-index:-1000}.swiper-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide{pointer-events:none;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.swiper-container-fade .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide-active,.swiper-container-fade .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-cube{overflow:visible}.swiper-container-cube .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1;visibility:hidden;-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;width:100%;height:100%}.swiper-container-cube .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-next,.swiper-container-cube .swiper-slide-next+.swiper-slide,.swiper-container-cube .swiper-slide-prev{pointer-events:auto;visibility:visible}.swiper-container-cube .swiper-slide-shadow-bottom,.swiper-container-cube .swiper-slide-shadow-left,.swiper-container-cube .swiper-slide-shadow-right,.swiper-container-cube .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-cube-shadow{position:absolute;left:0;bottom:0;width:100%;height:100%;background:#000;opacity:.6;-webkit-filter:blur(50px);filter:blur(50px);z-index:0}.swiper-container-flip{overflow:visible}.swiper-container-flip .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1}.swiper-container-flip .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-flip .swiper-slide-active,.swiper-container-flip .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-flip .swiper-slide-shadow-bottom,.swiper-container-flip .swiper-slide-shadow-left,.swiper-container-flip .swiper-slide-shadow-right,.swiper-container-flip .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-coverflow .swiper-wrapper{-ms-perspective:1200px}
--------------------------------------------------------------------------------