Commit 14571770fc947cdae489fefebcea11c578316adc

Authored by ly525
1 parent c532b500

refactor(ajax)

README.en.md
@@ -36,17 +36,16 @@ English | [简体中文](./README.md) @@ -36,17 +36,16 @@ English | [简体中文](./README.md)
36 - [ ] Photo Gallery 36 - [ ] Photo Gallery
37 - [ ] Third Party uncopyrighted Image Search 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 - [ ] Form Statistics 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 ### Installs 50 ### Installs
52 > proj: project root path 51 > proj: project root path
@@ -54,5 +53,14 @@ English | [简体中文](./README.md) @@ -54,5 +53,14 @@ English | [简体中文](./README.md)
54 1. Front End 53 1. Front End
55 Editor: please refer to: [`project/front-end/h5/README.md`](https://github.com/ly525/luban-h5/blob/dev/front-end/h5/README.md) 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 \ No newline at end of file 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 \ No newline at end of file 68 \ No newline at end of file
README.md
@@ -44,8 +44,8 @@ @@ -44,8 +44,8 @@
44 - [x] 创建、保存、更新作品 44 - [x] 创建、保存、更新作品
45 - [ ] 表单数据收集 45 - [ ] 表单数据收集
46 - [ ] 表单数据展示 46 - [ ] 表单数据展示
47 - - [ ] 在线预览  
48 - - [ ] 二维码预览 47 + - [x] 在线预览
  48 + - [x] 二维码预览
49 49
50 --- 50 ---
51 51
back-end/h5-api/README.md
@@ -13,3 +13,19 @@ strapi develop @@ -13,3 +13,19 @@ strapi develop
13 # default database is sqlite3(h5-api/.tmp/data.db) 13 # default database is sqlite3(h5-api/.tmp/data.db)
14 # visit http://locahost:1337/admin 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 \ No newline at end of file 32 \ No newline at end of file
front-end/h5/src/components/core/editor/index.js
@@ -43,6 +43,9 @@ export default { @@ -43,6 +43,9 @@ export default {
43 editingElement: state => state.editingElement, 43 editingElement: state => state.editingElement,
44 elements: state => state.editingPage.elements, 44 elements: state => state.editingPage.elements,
45 pages: state => state.work.pages 45 pages: state => state.work.pages
  46 + }),
  47 + ...mapState('loading', {
  48 + saveWork_loading: state => state.saveWork_loading
46 }) 49 })
47 }, 50 },
48 methods: { 51 methods: {
@@ -112,7 +115,7 @@ export default { @@ -112,7 +115,7 @@ export default {
112 </a-button-group> 115 </a-button-group>
113 </a-menu-item> 116 </a-menu-item>
114 <a-menu-item key="1" class="transparent-bg"><a-button type="primary" size="small" onClick={() => { this.previewVisible = true }}>预览</a-button></a-menu-item> 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 <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item> 119 <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item>
117 </a-menu> 120 </a-menu>
118 </a-layout-header> 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 // initial state 1 // initial state
2 const state = { 2 const state = {
3 - 3 + saveWork_loading: false
4 } 4 }
5 5
6 // getters 6 // getters
@@ -10,12 +10,16 @@ const getters = { @@ -10,12 +10,16 @@ const getters = {
10 10
11 // actions 11 // actions
12 const actions = { 12 const actions = {
13 - 13 + update ({ commit }, payload) {
  14 + commit('update', payload)
  15 + }
14 } 16 }
15 17
16 // mutations 18 // mutations
17 const mutations = { 19 const mutations = {
18 - 20 + update (state, { type, payload }) {
  21 + state[type] = payload
  22 + }
19 } 23 }
20 24
21 export default { 25 export default {
front-end/h5/src/store/modules/work.js
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 import Element from '../../components/core/models/element' 2 import Element from '../../components/core/models/element'
3 import strapi from '../../utils/strapi' 3 import strapi from '../../utils/strapi'
4 import Page from '../../components/core/models/page' 4 import Page from '../../components/core/models/page'
  5 +import { AxiosWrapper } from '../../utils/http.js'
5 6
6 export const actions = { 7 export const actions = {
7 previewWork ({ commit }, payload = {}) { 8 previewWork ({ commit }, payload = {}) {
@@ -26,13 +27,19 @@ export const actions = { @@ -26,13 +27,19 @@ export const actions = {
26 } 27 }
27 commit('setWork', work) 28 commit('setWork', work)
28 }, 29 },
29 - saveWork ({ commit, state }, payload = {}) { 30 + saveWork ({ commit, dispatch, state }, payload = {}) {
30 // update work with strapi 31 // update work with strapi
31 const work = { 32 const work = {
32 ...state.work, 33 ...state.work,
33 ...payload 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 fetchWork ({ commit, state }, workId) { 44 fetchWork ({ commit, state }, workId) {
38 strapi.getEntry('works', workId).then(entry => { 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 const ProxyAgent = require('proxy-agent') 1 const ProxyAgent = require('proxy-agent')
2 const isProd = process.env.NODE_ENV === 'production' 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 module.exports = { 7 module.exports = {
9 runtimeCompiler: true, 8 runtimeCompiler: true,
10 - publicPath, 9 + publicPath: isProd ? '/luban-h5/' : '/',
11 devServer: { 10 devServer: {
12 // proxy: API_ORIGIN 11 // proxy: API_ORIGIN
13 proxy: { 12 proxy: {
14 '/': { 13 '/': {
15 agent: new ProxyAgent('socks5://127.0.0.1:1086'), 14 agent: new ProxyAgent('socks5://127.0.0.1:1086'),
16 - target: API_ORIGIN, 15 + target: isProd ? PROD_API_ORIGIN : DEV_API_ORIGIN,
17 changeOrigin: true 16 changeOrigin: true
18 } 17 }
19 } 18 }