Commit 14571770fc947cdae489fefebcea11c578316adc
1 parent
c532b500
refactor(ajax)
Showing
9 changed files
with
228 additions
and
27 deletions
README.en.md
| ... | ... | @@ -36,17 +36,16 @@ English | [简体中文](./README.md) |
| 36 | 36 | - [ ] Photo Gallery |
| 37 | 37 | - [ ] Third Party uncopyrighted Image Search |
| 38 | 38 | |
| 39 | -4. Data Statistics | |
| 39 | + | |
| 40 | +4. back-end API | |
| 41 | + - [x] create work | |
| 42 | + - [x] save work | |
| 43 | + - [x] update work | |
| 40 | 44 | - [ ] Form Statistics |
| 45 | + - [x] Online Preview | |
| 46 | + - [x] QR Code Preview | |
| 41 | 47 | |
| 42 | -5. Others | |
| 43 | - - [ ] Online preview | |
| 44 | - - [ ] QR Code Preview | |
| 45 | - | |
| 46 | -### Technology Stack (current) | |
| 47 | - 1. Front end: Vue.js | |
| 48 | - 2. Back End: Strapi | |
| 49 | - 3. Storage: Sqlite | |
| 48 | +--- | |
| 50 | 49 | |
| 51 | 50 | ### Installs |
| 52 | 51 | > proj: project root path |
| ... | ... | @@ -54,5 +53,14 @@ English | [简体中文](./README.md) |
| 54 | 53 | 1. Front End |
| 55 | 54 | Editor: please refer to: [`project/front-end/h5/README.md`](https://github.com/ly525/luban-h5/blob/dev/front-end/h5/README.md) |
| 56 | 55 | |
| 57 | -### Front-End Component Explanation | |
| 58 | -1. `lbp-`: `lu-ban-plugin-`, means `Luban H5 plugin`, location: `proj/front-end/h5/src/components/plugins` | |
| 59 | 56 | \ No newline at end of file |
| 57 | + | |
| 58 | +--- | |
| 59 | +### More Explanation | |
| 60 | +#### Front-End Component Explanation | |
| 61 | +1. `lbp-`: `lu-ban-plugin-`, means `Luban H5 plugin`, location: `proj/front-end/h5/src/components/plugins` | |
| 62 | + | |
| 63 | + | |
| 64 | +#### Technology Stack (current) | |
| 65 | + 1. Front end: Vue.js | |
| 66 | + 2. Back End: Strapi | |
| 67 | + 3. Storage: Sqlite | |
| 60 | 68 | \ No newline at end of file | ... | ... |
README.md
back-end/h5-api/README.md
| ... | ... | @@ -13,3 +13,19 @@ strapi develop |
| 13 | 13 | # default database is sqlite3(h5-api/.tmp/data.db) |
| 14 | 14 | # visit http://locahost:1337/admin |
| 15 | 15 | ``` |
| 16 | + | |
| 17 | + | |
| 18 | +## Features(zh) | |
| 19 | + - [x] 创建、保存、更新作品 | |
| 20 | + - [x] 在线预览 | |
| 21 | + - [x] 二维码预览 | |
| 22 | + - [ ] 表单数据收集 | |
| 23 | + - [ ] 表单数据展示 | |
| 24 | + | |
| 25 | +## Features(en) | |
| 26 | + - [x] create work | |
| 27 | + - [x] save work | |
| 28 | + - [x] update work | |
| 29 | + - [x] Online Preview | |
| 30 | + - [x] QR Code Preview | |
| 31 | + - [ ] Form Statistics | |
| 16 | 32 | \ No newline at end of file | ... | ... |
front-end/h5/src/components/core/editor/index.js
| ... | ... | @@ -43,6 +43,9 @@ export default { |
| 43 | 43 | editingElement: state => state.editingElement, |
| 44 | 44 | elements: state => state.editingPage.elements, |
| 45 | 45 | pages: state => state.work.pages |
| 46 | + }), | |
| 47 | + ...mapState('loading', { | |
| 48 | + saveWork_loading: state => state.saveWork_loading | |
| 46 | 49 | }) |
| 47 | 50 | }, |
| 48 | 51 | methods: { |
| ... | ... | @@ -112,7 +115,7 @@ export default { |
| 112 | 115 | </a-button-group> |
| 113 | 116 | </a-menu-item> |
| 114 | 117 | <a-menu-item key="1" class="transparent-bg"><a-button type="primary" size="small" onClick={() => { this.previewVisible = true }}>预览</a-button></a-menu-item> |
| 115 | - <a-menu-item key="2" class="transparent-bg"><a-button size="small" onClick={() => this.saveWork()}>保存</a-button></a-menu-item> | |
| 118 | + <a-menu-item key="2" class="transparent-bg"><a-button size="small" onClick={() => this.saveWork()} loading={this.saveWork_loading}>保存</a-button></a-menu-item> | |
| 116 | 119 | <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item> |
| 117 | 120 | </a-menu> |
| 118 | 121 | </a-layout-header> | ... | ... |
front-end/h5/src/constants/api.js
| 1 | -export const API_HOST = 'https://radiant-depths-79548.herokuapp.com' | |
| 2 | -export const API_PORT = '' | |
| 3 | -export const API_ORIGIN = `${API_HOST}:${API_PORT}` | |
| 1 | +// export const API_HOST = 'https://radiant-depths-79548.herokuapp.com' | |
| 2 | +// export const API_PORT = '' | |
| 3 | +// export const API_ORIGIN = `${API_HOST}:${API_PORT}` | |
| 4 | +export const API_ORIGIN = 'http://localhost:1337' | ... | ... |
front-end/h5/src/store/modules/loading.js
| 1 | 1 | // initial state |
| 2 | 2 | const state = { |
| 3 | - | |
| 3 | + saveWork_loading: false | |
| 4 | 4 | } |
| 5 | 5 | |
| 6 | 6 | // getters |
| ... | ... | @@ -10,12 +10,16 @@ const getters = { |
| 10 | 10 | |
| 11 | 11 | // actions |
| 12 | 12 | const actions = { |
| 13 | - | |
| 13 | + update ({ commit }, payload) { | |
| 14 | + commit('update', payload) | |
| 15 | + } | |
| 14 | 16 | } |
| 15 | 17 | |
| 16 | 18 | // mutations |
| 17 | 19 | const mutations = { |
| 18 | - | |
| 20 | + update (state, { type, payload }) { | |
| 21 | + state[type] = payload | |
| 22 | + } | |
| 19 | 23 | } |
| 20 | 24 | |
| 21 | 25 | export default { | ... | ... |
front-end/h5/src/store/modules/work.js
| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | import Element from '../../components/core/models/element' |
| 3 | 3 | import strapi from '../../utils/strapi' |
| 4 | 4 | import Page from '../../components/core/models/page' |
| 5 | +import { AxiosWrapper } from '../../utils/http.js' | |
| 5 | 6 | |
| 6 | 7 | export const actions = { |
| 7 | 8 | previewWork ({ commit }, payload = {}) { |
| ... | ... | @@ -26,13 +27,19 @@ export const actions = { |
| 26 | 27 | } |
| 27 | 28 | commit('setWork', work) |
| 28 | 29 | }, |
| 29 | - saveWork ({ commit, state }, payload = {}) { | |
| 30 | + saveWork ({ commit, dispatch, state }, payload = {}) { | |
| 30 | 31 | // update work with strapi |
| 31 | 32 | const work = { |
| 32 | 33 | ...state.work, |
| 33 | 34 | ...payload |
| 34 | 35 | } |
| 35 | - strapi.updateEntry('works', state.work.id, work) | |
| 36 | + | |
| 37 | + new AxiosWrapper({ | |
| 38 | + dispatch, | |
| 39 | + loading_name: 'saveWork_loading', | |
| 40 | + successMsg: '保存作品成功', | |
| 41 | + customRequest: strapi.updateEntry.bind(strapi) | |
| 42 | + }).put('works', state.work.id, work) | |
| 36 | 43 | }, |
| 37 | 44 | fetchWork ({ commit, state }, workId) { |
| 38 | 45 | strapi.getEntry('works', workId).then(entry => { | ... | ... |
front-end/h5/src/utils/http.js
0 → 100644
| 1 | +import axios from 'axios' | |
| 2 | +import { message } from 'ant-design-vue' | |
| 3 | + | |
| 4 | +message.config({ | |
| 5 | + maxCount: 3 | |
| 6 | +}) | |
| 7 | + | |
| 8 | +export const myMessage = message | |
| 9 | + | |
| 10 | +export const client = axios.create({ | |
| 11 | + baseURL: '/v1', | |
| 12 | + responseType: 'json' | |
| 13 | +}) | |
| 14 | +export const baseClient = axios.create({ | |
| 15 | + responseType: 'json' | |
| 16 | +}) | |
| 17 | + | |
| 18 | +export class AxiosWrapper { | |
| 19 | + // eslint-disable-next-line camelcase | |
| 20 | + constructor ({ name = 'default', loading_name, responseType = 'json', headers, dispatch, router, successMsg, failMsg, successCallback, failCallback, customRequest }) { | |
| 21 | + this.name = name | |
| 22 | + // eslint-disable-next-line camelcase | |
| 23 | + this.loading_name = loading_name | |
| 24 | + // eslint-disable-next-line camelcase | |
| 25 | + this.responseType = responseType | |
| 26 | + this.dispatch = dispatch | |
| 27 | + this.router = router | |
| 28 | + this.successMsg = successMsg | |
| 29 | + this.failMsg = failMsg | |
| 30 | + this.customRequest = customRequest | |
| 31 | + this.successCallback = successCallback | |
| 32 | + this.failCallback = failCallback | |
| 33 | + this.source = axios.CancelToken.source() | |
| 34 | + this.instance = axios.create({ | |
| 35 | + // baseURL: '/v1', | |
| 36 | + responseType, | |
| 37 | + headers, | |
| 38 | + cancelToken: this.source.token | |
| 39 | + }) | |
| 40 | + this.instance.interceptors.response.use(response => { | |
| 41 | + // Do something with response data | |
| 42 | + return Promise.resolve(response) | |
| 43 | + }, error => { | |
| 44 | + // Do something with response error | |
| 45 | + return Promise.reject(error) | |
| 46 | + }) | |
| 47 | + } | |
| 48 | + | |
| 49 | + get (...args) { | |
| 50 | + this.setDefaultLoadingName(args) | |
| 51 | + | |
| 52 | + this.setLoadingValue(true) | |
| 53 | + return this.instance.get(...args).then(response => { | |
| 54 | + const handler = this.getCommonResponseHandler({ failMsg: 'Query Failed.' }) | |
| 55 | + handler.call(this, response) | |
| 56 | + }).catch(error => { | |
| 57 | + // handle error | |
| 58 | + myMessage.error(error.message) | |
| 59 | + }).finally(() => this.setLoadingValue(false)) | |
| 60 | + } | |
| 61 | + | |
| 62 | + post (...args) { | |
| 63 | + this.setDefaultLoadingName(args) | |
| 64 | + | |
| 65 | + this.setLoadingValue(true) | |
| 66 | + return this.instance.post(...args).then(response => { | |
| 67 | + const handler = this.getCommonResponseHandler({ failMsg: 'Save Failed.' }) | |
| 68 | + handler.call(this, response) | |
| 69 | + }).catch(error => { | |
| 70 | + // handle error | |
| 71 | + myMessage.error(error.message) | |
| 72 | + }).finally(() => this.setLoadingValue(false)) | |
| 73 | + } | |
| 74 | + | |
| 75 | + put (...args) { | |
| 76 | + this.setDefaultLoadingName(args) | |
| 77 | + | |
| 78 | + this.setLoadingValue(true) | |
| 79 | + if (this.customRequest) { | |
| 80 | + return this.customRequest(...args) | |
| 81 | + .then(data => { | |
| 82 | + const handler = this.getCommonResponseHandler({ failMsg: 'Save Failed.' }) | |
| 83 | + handler.call(this, { data: { status: 200, data } }) | |
| 84 | + }) | |
| 85 | + .finally(() => this.setLoadingValue(false)) | |
| 86 | + } | |
| 87 | + return this.instance.put(...args).then(response => { | |
| 88 | + const handler = this.getCommonResponseHandler({ failMsg: 'Save Failed.' }) | |
| 89 | + // handler.call(this, response) | |
| 90 | + handler() | |
| 91 | + }).catch(error => { | |
| 92 | + // handle error | |
| 93 | + myMessage.error(error.message) | |
| 94 | + }).finally(() => this.setLoadingValue(false)) | |
| 95 | + } | |
| 96 | + | |
| 97 | + delete (...args) { | |
| 98 | + this.setDefaultLoadingName(args) | |
| 99 | + | |
| 100 | + this.setLoadingValue(true) | |
| 101 | + return this.instance.delete(...args).then(response => { | |
| 102 | + const handler = this.getCommonResponseHandler({ failMsg: 'Save Failed.' }) | |
| 103 | + handler.call(this, response) | |
| 104 | + }).catch(error => { | |
| 105 | + // handle error | |
| 106 | + myMessage.error(error.message) | |
| 107 | + }).finally(() => this.setLoadingValue(false)) | |
| 108 | + } | |
| 109 | + | |
| 110 | + cancel (reason) { | |
| 111 | + this.source.cancel(reason) | |
| 112 | + } | |
| 113 | + | |
| 114 | + setLoadingValue (payload) { | |
| 115 | + this.dispatch('loading/update', { type: this.loading_name, payload }, { root: true }) | |
| 116 | + } | |
| 117 | + | |
| 118 | + setDefaultLoadingName (...args) { | |
| 119 | + if (!this.loading_name) { | |
| 120 | + let url = args[0] | |
| 121 | + if (url.indexOf('/') !== -1) { | |
| 122 | + let us = url.split('/') | |
| 123 | + url = us[us.length - 1] | |
| 124 | + } | |
| 125 | + if (url.indexOf('?') !== -1) { | |
| 126 | + let us = url.split('?') | |
| 127 | + url = us[0] | |
| 128 | + } | |
| 129 | + this.loading_name = `${url}_loading` | |
| 130 | + } | |
| 131 | + } | |
| 132 | + | |
| 133 | + getCommonResponseHandler ({ failMsg } = {}) { | |
| 134 | + return (response) => { | |
| 135 | + if (!response.data) { | |
| 136 | + myMessage.warn(this.failMsg || failMsg) | |
| 137 | + } else if (response.data.status === 200) { | |
| 138 | + this.successMsg && myMessage.success(this.successMsg) | |
| 139 | + if (this.successCallback) { | |
| 140 | + this.successCallback(response) | |
| 141 | + } else { | |
| 142 | + // this.dispatch({ type: this.name, payload: response.data.data }) | |
| 143 | + } | |
| 144 | + } else if (this.responseType === 'json') { | |
| 145 | + myMessage.error(response.data.msg) | |
| 146 | + if (response.data.status === 401) { | |
| 147 | + if (this.router) { | |
| 148 | + this.router.push('/login') | |
| 149 | + } | |
| 150 | + } else { | |
| 151 | + alert(response.data.msg) | |
| 152 | + if (this.failCallback) { | |
| 153 | + this.failCallback(response) | |
| 154 | + } | |
| 155 | + } | |
| 156 | + } else { | |
| 157 | + if (this.successCallback) { | |
| 158 | + this.successCallback(response) | |
| 159 | + } | |
| 160 | + } | |
| 161 | + } | |
| 162 | + } | |
| 163 | +} | ... | ... |
front-end/h5/vue.config.js
| 1 | 1 | const ProxyAgent = require('proxy-agent') |
| 2 | 2 | const isProd = process.env.NODE_ENV === 'production' |
| 3 | 3 | |
| 4 | -const API_ORIGIN = 'https://radiant-depths-79548.herokuapp.com' | |
| 5 | -const publicPath = isProd ? '/luban-h5/' : '/' | |
| 6 | -// const proxy = isProd ? API_ORIGIN : 'http://localhost:1337' | |
| 4 | +const PROD_API_ORIGIN = 'https://radiant-depths-79548.herokuapp.com' | |
| 5 | +const DEV_API_ORIGIN = 'http://localhost:1337' | |
| 7 | 6 | |
| 8 | 7 | module.exports = { |
| 9 | 8 | runtimeCompiler: true, |
| 10 | - publicPath, | |
| 9 | + publicPath: isProd ? '/luban-h5/' : '/', | |
| 11 | 10 | devServer: { |
| 12 | 11 | // proxy: API_ORIGIN |
| 13 | 12 | proxy: { |
| 14 | 13 | '/': { |
| 15 | 14 | agent: new ProxyAgent('socks5://127.0.0.1:1086'), |
| 16 | - target: API_ORIGIN, | |
| 15 | + target: isProd ? PROD_API_ORIGIN : DEV_API_ORIGIN, | |
| 17 | 16 | changeOrigin: true |
| 18 | 17 | } |
| 19 | 18 | } | ... | ... |