diff --git a/README.md b/README.md index 32e3b82..4fbf01d 100644 --- a/README.md +++ b/README.md @@ -17,18 +17,21 @@ - 2018.10 - 2019.03 开发, 上线, 迭代 - 2019.06 管理后台添加权限 - 2019.07 小程序登录位置调整, 广告位添加 + - 2019.09 管理后台手机端 ## 项目目录 - [ApiServer API服务端](https://github.com/klren0312/ironInfoWeapp/tree/master/ApiServer) - - [ServerWeb WEB管理前端](https://github.com/klren0312/ironInfoWeapp/tree/master/ServerWeb) + - [ServerWeb WEB管理后台PC端](https://github.com/klren0312/ironInfoWeapp/tree/master/ServerWeb) + - [ServerWebMobile WEB管理后台手机端](https://github.com/klren0312/ironInfoWeapp/tree/master/ServerWebMobile) - [Weapp 小程序与H5端](https://github.com/klren0312/ironInfoWeapp/tree/master/Weapp) - [相关文档](https://github.com/klren0312/ironInfoWeapp/tree/master/doc) ## 开源计划 -* [x] API服务端 -* [x] 管理前端 +* [x] API服务端 +* [x] 管理后台PC端 +* [x] 管理后台手机端 * [x] 小程序与H5 * [x] 文档: 需求文档 * [x] 文档: API文档 @@ -64,6 +67,9 @@ # 管理后台 ![](./Weapp/img/backend.png) +# 管理后台手机端 +![](./ServerWebMobile/imgs/mobile.jpg) + ## Stargazers over time [![Stargazers over time](https://starchart.cc/klren0312/ironInfoWeapp.svg)](https://starchart.cc/klren0312/ironInfoWeapp) diff --git a/ServerWebMobile/.eslintrc.js b/ServerWebMobile/.eslintrc.js new file mode 100644 index 0000000..a1fd69f --- /dev/null +++ b/ServerWebMobile/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + root: true, + env: { + node: true + }, + 'extends': [ + 'plugin:vue/essential', + '@vue/standard' + ], + rules: { + 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' + }, + parserOptions: { + parser: 'babel-eslint' + } +} \ No newline at end of file diff --git a/ServerWebMobile/.gitignore b/ServerWebMobile/.gitignore new file mode 100644 index 0000000..953b1ac --- /dev/null +++ b/ServerWebMobile/.gitignore @@ -0,0 +1,25 @@ +.DS_Store +node_modules +/dist + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw* + +# lock +package-lock.json +yarn.lock \ No newline at end of file diff --git a/ServerWebMobile/.postcssrc.js b/ServerWebMobile/.postcssrc.js new file mode 100644 index 0000000..7fa3b3b --- /dev/null +++ b/ServerWebMobile/.postcssrc.js @@ -0,0 +1,9 @@ +module.exports = { + plugins: { + 'autoprefixer': {}, + 'postcss-pxtorem': { + 'rootValue': 100, + 'propWhiteList': [] + } + } +} \ No newline at end of file diff --git a/ServerWebMobile/README.md b/ServerWebMobile/README.md new file mode 100644 index 0000000..eab66a3 --- /dev/null +++ b/ServerWebMobile/README.md @@ -0,0 +1,46 @@ +# tlgc + +## Project setup +``` +yarn install +``` + +### Compiles and hot-reloads for development +``` +yarn run serve +``` + +### Compiles and minifies for production +``` +yarn run build +``` + +### Run your tests +``` +yarn run test +``` + +### Lints and fixes files +``` +yarn run lint +``` + +### 使用相关库 + + - "vue": "^2.6.6", + - "vue-router": "^3.0.1", + - "vuex": "^3.0.1", + - "axios": "^0.18.0", + - "echarts": "^4.1.0", + - "element-ui": "^2.5.4", + - "normalize.css": "^8.0.1", + - "nprogress": "^0.2.0", + - "sortablejs": "^1.8.3", + - "v-charts": "^1.19.0", + - "vm-markdown": "^0.2.8", + - "zstorage": "^1.0.4" + +### 注意: +1. api全部封装在`src\api`中, 每个页面一个`*.api.js` +2. 后端地址配在`public\index.html` +3. 登录态维护使用`localStorage` \ No newline at end of file diff --git a/ServerWebMobile/babel.config.js b/ServerWebMobile/babel.config.js new file mode 100644 index 0000000..83d365b --- /dev/null +++ b/ServerWebMobile/babel.config.js @@ -0,0 +1,14 @@ +module.exports = { + presets: [ + '@vue/app' + ], + plugins: [ + [ + 'import', + { + libraryName: 'mand-mobile', + libraryDirectory: 'lib' + } + ] + ] +} \ No newline at end of file diff --git a/ServerWebMobile/imgs/mobile.jpg b/ServerWebMobile/imgs/mobile.jpg new file mode 100644 index 0000000..f3eb370 Binary files /dev/null and b/ServerWebMobile/imgs/mobile.jpg differ diff --git a/ServerWebMobile/package.json b/ServerWebMobile/package.json new file mode 100644 index 0000000..69a8c44 --- /dev/null +++ b/ServerWebMobile/package.json @@ -0,0 +1,41 @@ +{ + "name": "tlgc", + "version": "0.1.0", + "private": true, + "scripts": { + "serve": "vue-cli-service serve", + "build": "vue-cli-service build" + }, + "dependencies": { + "axios": "^0.18.0", + "echarts": "^4.1.0", + "element-ui": "^2.5.4", + "lz-string": "^1.4.4", + "normalize.css": "^8.0.1", + "nprogress": "^0.2.0", + "sortablejs": "^1.8.3", + "v-charts": "^1.19.0", + "vm-markdown": "^0.2.8", + "vue": "^2.6.6", + "vue-router": "^3.0.1", + "vuex": "^3.0.1", + "zstorage": "^1.0.4" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "^3.0.5", + "@vue/cli-service": "^3.0.5", + "node-sass": "^4.9.0", + "sass-loader": "^7.1.0", + "vue-template-compiler": "^2.5.21" + }, + "postcss": { + "plugins": { + "autoprefixer": {} + } + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" + ] +} diff --git a/ServerWebMobile/public/favicon.ico b/ServerWebMobile/public/favicon.ico new file mode 100644 index 0000000..c7b9a43 Binary files /dev/null and b/ServerWebMobile/public/favicon.ico differ diff --git a/ServerWebMobile/public/index.html b/ServerWebMobile/public/index.html new file mode 100644 index 0000000..7bd4ffc --- /dev/null +++ b/ServerWebMobile/public/index.html @@ -0,0 +1,25 @@ + + + + + + + + + + + 治电管理后台 + + + +
+ + + + diff --git a/ServerWebMobile/src/App.vue b/ServerWebMobile/src/App.vue new file mode 100644 index 0000000..5e1c452 --- /dev/null +++ b/ServerWebMobile/src/App.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/ServerWebMobile/src/apis/article.api.js b/ServerWebMobile/src/apis/article.api.js new file mode 100644 index 0000000..07cf7be --- /dev/null +++ b/ServerWebMobile/src/apis/article.api.js @@ -0,0 +1,41 @@ +import request from './request' + +export function getArticle (queryString) { + return request.get(`/article?${queryString}`) +} + +export function getArticleById (id) { + return request.get(`/article?id=${id}`) +} + +export function updateArticleStatus (id, status) { + return request.patch('/article', { + id: id, + status: status + }) +} + +export function updateArticle (id, title, content) { + return request.put('/article', { + id: id, + title: title, + content: content + }) +} + +export function publishArticle (title, content) { + return request.post('/article', { + title: title, + content: content + }) +} + +export function deleteArticle (id) { + return request({ + method: 'DELETE', + url: '/article', + data: { + id: id + } + }) +} diff --git a/ServerWebMobile/src/apis/home.api.js b/ServerWebMobile/src/apis/home.api.js new file mode 100644 index 0000000..212f769 --- /dev/null +++ b/ServerWebMobile/src/apis/home.api.js @@ -0,0 +1,9 @@ +import request from './request' + +export function getHomeSum () { + return request.get('/homeSum') +} + +export function getWxSum () { + return request.get('/wechatUser') +} diff --git a/ServerWebMobile/src/apis/hot.api.js b/ServerWebMobile/src/apis/hot.api.js new file mode 100644 index 0000000..7d98051 --- /dev/null +++ b/ServerWebMobile/src/apis/hot.api.js @@ -0,0 +1,32 @@ +import request from './request' + +export function getHot () { + return request({ + url: `/hot`, + method: 'GET' + }) +} + +export function updateSort (hot) { + return request.put('/hot', { + list: hot + }) +} + +export function deleteHot (id) { + return request({ + url: '/hot', + method: 'DELETE', + data: { + id: id + } + }) +} + +export function createHot (hotForm) { + return request({ + url: '/hot', + method: 'post', + data: hotForm + }) +} diff --git a/ServerWebMobile/src/apis/iron.api.js b/ServerWebMobile/src/apis/iron.api.js new file mode 100644 index 0000000..06e2ec1 --- /dev/null +++ b/ServerWebMobile/src/apis/iron.api.js @@ -0,0 +1,49 @@ +import request from './request' + +export function getIron (queryString) { + return request({ + url: `/iron?${queryString}`, + method: 'GET' + }) +} + +export function getAllIron () { + return request.get('/iron/all') +} + +export function updateIron (iron) { + return request({ + method: 'PATCH', + url: '/iron', + data: iron + }) +} + +export function createIron (ironForm) { + return request({ + url: '/iron', + method: 'post', + data: ironForm + }) +} + +export function addNewPrice (id, value) { + return request({ + url: `/iron/price`, + method: 'POST', + data: { + id: id, + price: parseFloat(value) + } + }) +} + +export function deleteIron (id) { + return request({ + url: '/iron', + method: 'DELETE', + data: { + id: id + } + }) +} diff --git a/ServerWebMobile/src/apis/log.api.js b/ServerWebMobile/src/apis/log.api.js new file mode 100644 index 0000000..86abf69 --- /dev/null +++ b/ServerWebMobile/src/apis/log.api.js @@ -0,0 +1,8 @@ +import request from './request' + +export function getLog (queryString) { + return request({ + url: `/log?${queryString}`, + method: 'GET' + }) +} diff --git a/ServerWebMobile/src/apis/request.js b/ServerWebMobile/src/apis/request.js new file mode 100644 index 0000000..5456040 --- /dev/null +++ b/ServerWebMobile/src/apis/request.js @@ -0,0 +1,64 @@ +import axios from 'axios' +import router from '../router' +import Storage from 'zstorage' +import store from '../store' +import { Toast } from 'mand-mobile' +// create an axios instance +const service = axios.create({ + baseURL: store.state.baseUrl, + timeout: 5000 +}) + +service.interceptors.request.use( + config => { + let token = Storage.get('admin_user') ? Storage.get('admin_user').token : '' + // console.log(token) + if (token) { + config.headers['Authorization'] = token + config.headers['Content-Type'] = 'application/json' + } + return config + }, + error => { + Promise.reject(error) + } +) + +service.interceptors.response.use( + response => { + try { + let req = JSON.parse(response.request.response) + if (req.err_code === 401) { + store.commit('LOG_OUT') + router.replace({ + path: '/login' + }) + return true + } + if (response.data.code === 200) { + return response.data.data + } else { + Toast.failed(response.data.data) + } + } catch (e) { // 用于文件下载 + return response.data + } + }, + error => { + if (error.response) { + switch (error.response.status) { + case 401: + // 返回 401 清除token信息并跳转到登录页面 + store.dispatch('SET_USER', null) + router.replace({ + path: '/login' + }) + break + default: + Toast.failed(error.response.data.message) + } + } + return Promise.reject(error.response.data) // 返回接口返回的错误信息 + }) + +export default service diff --git a/ServerWebMobile/src/apis/user.api.js b/ServerWebMobile/src/apis/user.api.js new file mode 100644 index 0000000..6069267 --- /dev/null +++ b/ServerWebMobile/src/apis/user.api.js @@ -0,0 +1,36 @@ +import request from './request' + +export function getUser (queryString) { + return request({ + url: `/user?${queryString}`, + method: 'GET' + }) +} + +export function updateUser (edit) { + return request({ + url: `/user`, + method: 'PUT', + data: { + id: edit.id, + password: edit.password, + email: edit.email + } + }) +} + +export function addUser (user) { + return request({ + url: '/user/register', + method: 'post', + data: user + }) +} + +export function login (user) { + return request({ + url: `/user/login`, + method: 'post', + data: user + }) +} diff --git a/ServerWebMobile/src/apis/wechat.api.js b/ServerWebMobile/src/apis/wechat.api.js new file mode 100644 index 0000000..cc44af8 --- /dev/null +++ b/ServerWebMobile/src/apis/wechat.api.js @@ -0,0 +1,21 @@ +import request from './request' + +/** + * 微信登录 + */ +export function weLogin () { + return request({ + url: `/wechat/login`, + method: 'GET' + }) +} + +/** + * 获取微信好友 + */ +export function weFriends () { + return request({ + url: `/wechat/friends`, + method: 'GET' + }) +} diff --git a/ServerWebMobile/src/apis/wuser.api.js b/ServerWebMobile/src/apis/wuser.api.js new file mode 100644 index 0000000..5d5374e --- /dev/null +++ b/ServerWebMobile/src/apis/wuser.api.js @@ -0,0 +1,8 @@ +import request from './request' + +export function getWuser (queryString) { + return request({ + url: `/wuser?${queryString}`, + method: 'GET' + }) +} diff --git a/ServerWebMobile/src/assets/global.css b/ServerWebMobile/src/assets/global.css new file mode 100644 index 0000000..8fe2d40 --- /dev/null +++ b/ServerWebMobile/src/assets/global.css @@ -0,0 +1,6 @@ +* { + margin: 0; + padding: 0; + list-style: none; + box-sizing: border-box; +} \ No newline at end of file diff --git a/ServerWebMobile/src/assets/responsive.js b/ServerWebMobile/src/assets/responsive.js new file mode 100644 index 0000000..b011b22 --- /dev/null +++ b/ServerWebMobile/src/assets/responsive.js @@ -0,0 +1,17 @@ +(function (window, document) { + function resize () { + var ww = window.innerWidth + if (ww > window.screen.width) { + window.requestAnimationFrame(resize) + } else { + if (ww > 750) { + ww = 750 + } + document.documentElement.style.fontSize = ww * 100 / 750 + 'px' + } + } + + resize() + + window.addEventListener('resize', resize) +})(window, document) diff --git a/ServerWebMobile/src/assets/tlgc.png b/ServerWebMobile/src/assets/tlgc.png new file mode 100644 index 0000000..8dfab4f Binary files /dev/null and b/ServerWebMobile/src/assets/tlgc.png differ diff --git a/ServerWebMobile/src/components/ZCard.vue b/ServerWebMobile/src/components/ZCard.vue new file mode 100644 index 0000000..b16052d --- /dev/null +++ b/ServerWebMobile/src/components/ZCard.vue @@ -0,0 +1,138 @@ + + + diff --git a/ServerWebMobile/src/components/ZCardP.vue b/ServerWebMobile/src/components/ZCardP.vue new file mode 100644 index 0000000..3097fe8 --- /dev/null +++ b/ServerWebMobile/src/components/ZCardP.vue @@ -0,0 +1,158 @@ + + + + + diff --git a/ServerWebMobile/src/components/ZHeader.vue b/ServerWebMobile/src/components/ZHeader.vue new file mode 100644 index 0000000..15dc09e --- /dev/null +++ b/ServerWebMobile/src/components/ZHeader.vue @@ -0,0 +1,56 @@ + + + diff --git a/ServerWebMobile/src/main.js b/ServerWebMobile/src/main.js new file mode 100644 index 0000000..646525d --- /dev/null +++ b/ServerWebMobile/src/main.js @@ -0,0 +1,38 @@ +import Vue from 'vue' +import FastClick from 'fastclick' +import 'normalize.css' +import App from './App.vue' +import './assets/responsive' +import './assets/global.css' +import Storage from 'zstorage' +import store from './store' +import router from './router' + +if ('addEventListener' in document && 'ontouchstart' in window) { + FastClick.prototype.focus = function (targetElement) { + targetElement.focus() + } + document.addEventListener('DOMContentLoaded', function () { + FastClick.attach(document.body) + }, false) +} + +Vue.prototype.$store = store +Vue.prototype.$storage = Storage + +Vue.config.productionTip = false + +// 判断登录态是否超时 +const userData = Storage.get('admin_user') + +if (userData === null || userData === undefined) { + store.commit('SET_USER', null) +} else { + store.commit('SET_USER', userData) +} + +new Vue({ + router, + store, + render: h => h(App) +}).$mount('#app') diff --git a/ServerWebMobile/src/router/index.js b/ServerWebMobile/src/router/index.js new file mode 100644 index 0000000..1dd3517 --- /dev/null +++ b/ServerWebMobile/src/router/index.js @@ -0,0 +1,83 @@ +import Vue from 'vue' +import Router from 'vue-router' +import store from '../store' +Vue.use(Router) + +const router = new Router({ + mode: 'history', + routes: [ + { + path: '/login', + name: 'login', + component: resolve => require(['@/views/loginPage'], resolve) + }, + { + name: 'index', + path: '/', + redirect: '/homePage' + }, + { + name: 'homePage', + path: '/homePage', + component: resolve => require(['@/views/homePage'], resolve) + }, + { + name: 'ironPage', + path: '/ironPage', + component: resolve => require(['@/views/ironPage'], resolve) + }, + { + name: 'ironForm', + path: '/ironForm', + component: resolve => require(['@/views/ironPage/form.vue'], resolve) + }, + { + name: 'hotPage', + path: '/hotPage', + component: resolve => require(['@/views/hotPage'], resolve) + }, + { + name: 'articlePage', + path: '/articlePage', + component: resolve => require(['@/views/articlePage'], resolve) + }, + { + name: 'articleDetails', + path: '/articlePage/:id', + component: resolve => require(['@/views/articlePage/details.vue'], resolve) + }, + { + name: 'weixinPage', + path: '/weixinPage', + component: resolve => require(['@/views/weixinPage'], resolve) + }, + { + name: 'userPage', + path: '/userPage', + component: resolve => require(['@/views/userPage'], resolve) + }, + { + name: 'logPage', + path: '/logPage', + component: resolve => require(['@/views/logPage'], resolve) + } + ] +}) + +router.beforeEach((to, from, next) => { + if (to.path === '/login') { + if (!store.state.user) { + next() + } else { + next({ path: '/' }) + } + } else { + if (store.state.user) { + next() + } else { + next({ path: `/login` }) + } + } +}) + +export default router diff --git a/ServerWebMobile/src/store/index.js b/ServerWebMobile/src/store/index.js new file mode 100644 index 0000000..b28f93c --- /dev/null +++ b/ServerWebMobile/src/store/index.js @@ -0,0 +1,45 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import Storage from 'zstorage' + +Vue.use(Vuex) + +const state = { + user: null, + /* eslint-disable */ + baseUrl: apiServer, + /* eslint-enable */ + token: '' +} + +const mutations = { + SET_USER (state, user) { + state.user = user + }, + LOG_OUT (state) { + state.user = null + Storage.set('admin_user', null) + }, + SET_TOKEN (state, token) { + state.token = token + } +} + +const actions = { + LOG_OUT ({ commit }) { + commit('LOG_OUT') + }, + SET_USER (state, user) { + state.commit('SET_USER', user) + }, + SET_TOKEN (state, token) { + state.commit('SET_TOKEN', token) + } +} + +export default new Vuex.Store({ + state, + mutations, + getters: {}, + actions: actions +}) diff --git a/ServerWebMobile/src/views/articlePage/details.vue b/ServerWebMobile/src/views/articlePage/details.vue new file mode 100644 index 0000000..5b678af --- /dev/null +++ b/ServerWebMobile/src/views/articlePage/details.vue @@ -0,0 +1,51 @@ + + + diff --git a/ServerWebMobile/src/views/articlePage/index.vue b/ServerWebMobile/src/views/articlePage/index.vue new file mode 100644 index 0000000..a2e4460 --- /dev/null +++ b/ServerWebMobile/src/views/articlePage/index.vue @@ -0,0 +1,146 @@ + + + diff --git a/ServerWebMobile/src/views/homePage/index.vue b/ServerWebMobile/src/views/homePage/index.vue new file mode 100644 index 0000000..78aba70 --- /dev/null +++ b/ServerWebMobile/src/views/homePage/index.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/ServerWebMobile/src/views/hotPage/index.vue b/ServerWebMobile/src/views/hotPage/index.vue new file mode 100644 index 0000000..f382008 --- /dev/null +++ b/ServerWebMobile/src/views/hotPage/index.vue @@ -0,0 +1,150 @@ + + + diff --git a/ServerWebMobile/src/views/ironPage/form.vue b/ServerWebMobile/src/views/ironPage/form.vue new file mode 100644 index 0000000..370f851 --- /dev/null +++ b/ServerWebMobile/src/views/ironPage/form.vue @@ -0,0 +1,64 @@ + + diff --git a/ServerWebMobile/src/views/ironPage/index.vue b/ServerWebMobile/src/views/ironPage/index.vue new file mode 100644 index 0000000..83d2de3 --- /dev/null +++ b/ServerWebMobile/src/views/ironPage/index.vue @@ -0,0 +1,238 @@ + + + diff --git a/ServerWebMobile/src/views/logPage/index.vue b/ServerWebMobile/src/views/logPage/index.vue new file mode 100644 index 0000000..e104e28 --- /dev/null +++ b/ServerWebMobile/src/views/logPage/index.vue @@ -0,0 +1,98 @@ + + + diff --git a/ServerWebMobile/src/views/loginPage/index.vue b/ServerWebMobile/src/views/loginPage/index.vue new file mode 100644 index 0000000..365f4c0 --- /dev/null +++ b/ServerWebMobile/src/views/loginPage/index.vue @@ -0,0 +1,84 @@ + + + diff --git a/ServerWebMobile/src/views/userPage/index.vue b/ServerWebMobile/src/views/userPage/index.vue new file mode 100644 index 0000000..7990a22 --- /dev/null +++ b/ServerWebMobile/src/views/userPage/index.vue @@ -0,0 +1,99 @@ + + + diff --git a/ServerWebMobile/src/views/weixinPage/index.vue b/ServerWebMobile/src/views/weixinPage/index.vue new file mode 100644 index 0000000..58f3493 --- /dev/null +++ b/ServerWebMobile/src/views/weixinPage/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/ServerWebMobile/vue.config.js b/ServerWebMobile/vue.config.js new file mode 100644 index 0000000..28bd22f --- /dev/null +++ b/ServerWebMobile/vue.config.js @@ -0,0 +1,40 @@ +const path = require('path') + +module.exports = { + productionSourceMap: false, + lintOnSave: process.env.NODE_ENV === 'development', + chainWebpack(config) { + config.plugins.delete('preload') + config.plugins.delete('prefetch') + config + .when(process.env.NODE_ENV === 'development', + config => config.devtool('cheap-source-map') + ) + // 分离打包 + config + .when(process.env.NODE_ENV !== 'development', + config => { + config + .optimization.splitChunks({ + chunks: 'all', + cacheGroups: { + libs: { + name: 'chunk-libs', + test: /[\\/]node_modules[\\/]/, + priority: 10, + chunks: 'initial' // only package third parties that are initially dependent + }, + commons: { + name: 'chunk-commons', + test: path.resolve('src/components/widgets'), // can customize your rules + minChunks: 2, // minimum common number + priority: 5, + reuseExistingChunk: true + } + } + }) + config.optimization.runtimeChunk('single') + } + ) + } +}