├── 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 | 6 | -------------------------------------------------------------------------------- /admin/src/views/About.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 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 | 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 | 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 | 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 | 29 | 30 | 35 | 36 | 43 | -------------------------------------------------------------------------------- /admin/src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 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 | 18 | 19 | 56 | -------------------------------------------------------------------------------- /admin/src/views/AdList.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 53 | 54 | -------------------------------------------------------------------------------- /admin/src/views/ArticleList.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 53 | 54 | -------------------------------------------------------------------------------- /admin/src/views/AdminUserList.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 53 | 54 | -------------------------------------------------------------------------------- /admin/src/views/CategoryList.vue: -------------------------------------------------------------------------------- 1 | 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 | 20 | 21 | 62 | -------------------------------------------------------------------------------- /admin/src/views/ItemList.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 58 | 59 | -------------------------------------------------------------------------------- /web/src/views/Article.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 54 | 55 | 72 | -------------------------------------------------------------------------------- /admin/src/views/HeroList.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 59 | 60 | -------------------------------------------------------------------------------- /admin/src/views/ItemEdit.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 65 | 66 | -------------------------------------------------------------------------------- /web/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 41 | 42 | 43 | 46 | -------------------------------------------------------------------------------- /admin/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 41 | 42 | 43 | 59 | -------------------------------------------------------------------------------- /admin/src/views/ArticleEdit.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 75 | 76 | 77 | 88 | 89 | -------------------------------------------------------------------------------- /web/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 66 | 67 | 103 | 104 | 129 | -------------------------------------------------------------------------------- /server/web/img/iconfont.57364c54.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by iconfont 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /web/src/assets/iconfont/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by iconfont 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 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 | 130 | 131 | 158 | 159 | 204 | -------------------------------------------------------------------------------- /admin/src/views/HeroEdit.vue: -------------------------------------------------------------------------------- 1 | 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 | 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">&#x33;</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} --------------------------------------------------------------------------------